JavaScript 基礎介紹(運算子、型別與文法)
陳述式與表達式
- 陳述式( Statement ):JS的語句類型,用於命令執行指定的一系列操作,最大的特徵是不會回傳結果,使用如下。
- 流程控制:
block
、break
、if...else
。 - 宣告:
var
、let
、const
。 - 函數(function)
// 函式陳述式、具名函式
function callName() {
.....
}- 迭代(Iteration);for迴圈等等。
- 可以參考MDN裡面對陳述式與宣告的詳細說明及舉例
- 流程控制:
- 表達式( Expression ):又可稱為表示式、運算式,經常可透過一些符號結合上下語句運算並回傳結果。
- 運算子:
+
、-
、*
、/
、%
,一般四則運算、餘數。 - 函數(function)
// 函式表達式、匿名函式
var callName = function() {
.....
} - 運算子:
常見誤解:
Block結構可以內含Statement,或是Expression作為物件實字 (Object Literal)。
- Statement如果把這段block賦值給另一個變數,則會出現錯誤:
{
var ming = '小明'
}若用ES6的const或let宣告變數,則該變數的作用域僅會在他所屬的block內。var a = {
var ming = '小明'
}
//錯誤{
const ming = '小明'
}
console.log(ming); //ming is not definded - 物件實字block裡面的是expression,所以他可以被賦值給變數:
{
ming: '小明'
}var a = {
ming: '小明'
}
ASI (Automatic Semicolon Insertion)
按照 ECMAScript 標準,一些 特定語句(statement) 必須以分號結尾。分號代表這段語句的終止。
但是有時候為了方便,這些分號是有可以省略的。這種情況下解釋器會自己判斷語句該在哪裡終止。這種行為被叫做 “自動插入分號”,簡稱 ASI (Automatic Semicolon Insertion) 。
特定語句有:
- 空語句
- let
- const
- import
- export
- 變量賦值
- 表達式
- debugger
- continue
- break
- return
- throw
ECMAScript 標準定義的 ASI 包括 三條規則 和 兩條例外。
三條規則是描述何時該自動插入分號:
- 解析器從左往右解析代碼(讀入 token),當碰到一個不能構成合法語句的 token 時,它會在以下幾種情況中在該 token 之前插入分號,此時這個不合群的 token 被稱為 offending token :
- 如果這個 token 跟上一個 token 之間有至少一個換行。
- 如果這個 token 是 }。
- 如果 前一個 token 是 ),它會試圖把前面的 token 理解成 do…while 語句並插入分號。
- 當解析到文件末尾發現語法還是有問題,就會在文件末尾插入分號。
- 當解析時碰到 restricted production 的語法(比如 return),並且在 restricted production 規定的 [no LineTerminator here]的地方發現換行,那麼換行的地方就會被插入分號。
- 分號不能被解析成空語句。
- 分號不能被解析成 for 語句頭部的兩個分號之一。
動態型別
JavaScript 是屬於動態型別,在執行階段才會確定型別,而型別是由賦予的值所定義的,且型別是可以變換的。
var name; |
型別轉換的陷阱
- 顯性的轉換( Explicit conversion ):是當原本變數的值,直接被賦予另一個型別的值
var num = 1; |
- 隱性的轉換( Implicit conversion ):須了解運算過程中型別的變化,不然會造成難以預期的結果。
//範例 |
原始型別[純值(Primitive Types)]及物件型別
JavaScript 是屬於動態型別,它定義了六種基本型別[或者稱為純值(Primitive Types)]及 Object 型別。
原始型別[純值(Primitive Types)]:
- Undefined:undefined 表示還不存在,這是 JavaScript 給所有變數的初始值。
- Null:null 也表示不存在,比較適合來表示一變數沒有值。
- Boolean:布林,用來判斷條件成立與否,僅有 true, false 兩個值。
- String:字串型別,這是一連串的字符所組成包覆在單引號或者雙引號內,都可以來表示字串。
- Number:數字型別,是一種 (浮點數),這種數值在極大值時會有精準度的問題。
另外還有以下三種都屬於此 Number 型別。- +Infinity
- -Infinity
- NaN (not a number,但屬於數字型別,強制轉型有時會出現此錯誤)
- Symbol(new):這是在 ES6 新推出的純值。
- BigInt(new) 整數數值(new)
物件型別:
除了上述的原始型別,其餘都是物件型別,包含很常使用的 “陣列”、”函式” 都屬於物件型別。
原始型別包裹物件
![原始型別包裹物件](/blog/2019/12/02/JavaScript-Basic-2/type.png)
原始型別可以使用的方法。除了 Null 跟 Undefined ,Boolean、Number、String、BigInt(new)、Symbol(new) 皆有其包裹物件
a = 'ming '; |
- length、toUpperCase()、trim() 為原始型別包裹物件內的方法。
- 雖然可以用 var e = new String(a); 但不建議用這種建構式來宣告取得型別,因為此為物件型別。
![](/blog/2019/12/02/JavaScript-Basic-2/type-2.png)
可以由 _proto_ 內得知原始型別可以使用的方法。
運算子
可透過符號或單詞來運算前後側的運算元,並且回傳一個結果。
![](/blog/2019/12/02/JavaScript-Basic-2/operator.png)
JavaScript 同時具有二元運算子及一元運算子, 以及一種特殊的 三元運算子,也就是 條件運算子。
運算元大部分屬於二元運算子,由左右兩邊的運算元搭配一個符號。
一元運算子
是只需要一個運算元的運算,位於運算子之前或之後。
如以下:
delete
運算子會刪除物件,物件的性質,或是陣列中指定 index 的物件。 語法是:
delete 物件名稱; |
typeof
運算子會回傳代表運算元類型。 運算元能是字串,變數,關鍵字,或是會回傳型態的物件。
typeof 運算元 |
條件(三元)運算子
三元運算子(又叫條件運算符),僅有的使用三個操作數的運算符。
一個條件後面會跟一個問號(?),如果條件為 truthy ,則問號後面的表達式A將會執行;表達式A後面跟著一個冒號(:),如果條件為 falsy ,則冒號後面的表達式B將會執行。
本運算符經常作為 if 語句的簡捷形式來使用。
優先性及相依性
優先性(Precedence)
決定運算子彼此之間被語法解析的方式
優先序較高的運算子會成為優先序較低的運算子的運算元
相依性(Associativity)
相依性決定運算方向
陷阱題 1:
console.log( 1 < 2 < 3) //true |
這跟優先性及相依性有很大的關係
- 因會先執行
console.log( 3 > 2)
,結果是 true - true 再跟 1 進行比較,所以會變成 console.log( true >1)
- 而 true 會進行型別的轉換,變成
console.log(1 > 1)
,因 1 不會大於 1 ,所以結果是 false
陷阱題 2:
var b = {}; |
- 因
b.a =1
為表達式,所以在 console 會回傳 1 - 而 a 所接收的結果是後面的
b.a =1
回傳的結果,所以 a 的結果為 1
寬鬆相等、嚴格相等以及隱含轉型
JavaScript 提供三種不同的值比較運算操作:
- 寬鬆相等:==
寬鬆相等會將比較值轉換成相同型別後比較。
轉換規則:
- 字串(String)、布林(Boolean)比較時會轉型為數字(Number)
可參照下方表格。
console.log( 17 == 0x11 ) //true |
- null、undefined寬鬆比對時不會轉型成數字。
console.log( Number(null), Number(undefined) ) //0, NaN |
- 物件比對
- 與非物件比對:物件比對會使用 基本型別包裹器(Primitive Wrapper)
valueOf()
或toString()
,轉換後再與非物件比對。console.log([10]) //10
console.log([10].valueOf() == 10) //true
// [10]透過valueOf()取回該物件相對應原始型別的值再進行比對
console.log(['A'].toString()) //A
console.log(['A'].toString() == 'A') //true
// [10]透過toString()取回該物件相對應原始型別的值再進行比對 - 與物件比對:物件與物件比對是使用 參考位置 比對,故比對結果為false。
console.log([] == []) //false
console.log({} == {}) //false - 與非物件比對:物件比對會使用 基本型別包裹器(Primitive Wrapper)
比 較 值 A |
|
|
|
|
|
|
|
---|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Number(B) |
|
|
|
|
|
|
Number(B) |
|
ToPrimitive(B) |
|
|
|
|
== B |
== B |
ToNumber(B) |
|
valueOf()
或toString()
方法,嘗試將物件轉換成原生值。
2. 嚴格相等:**===**
嚴格相等不會轉換型別,如果值是不同型別,就會被視為不相等。
例外:
console.log(NaN === NaN) //false; |
延伸:否定
- !==
- !=
參考:MDN 相等比較
Truthy 與 Falsy
在 JavaScript 這門程式語言,我們可以分成兩種「值」
- 第一種就是經過 ToBoolean 轉換後會變成 false,通常稱這些叫 「Falsy」值(假值)。
false | The keyword false. |
number | The number 0, +0, -0. |
"", '', `` | This is an empty string (the length of the string is zero). |
null | The absence of any value |
undefined | The primitive value |
NaN | not a number |
0n | BigInt, when used as a boolean, follows the same rule as a Number. 0n is falsy. |
if (false) |
- 而其他的部分都會是 true,則是 「Truthy」值(真值)。
if (true) |
邏輯運算子及函式預設值
邏輯運算子 (Logical Operator)
Operator | Syntax | Description |
---|---|---|
邏輯 AND (&&) | exprA && exprB |
|
邏輯 OR (||) | exprA || exprB |
|
邏輯 NOT (!) | !expr |
|
延伸:
var originCash = 500; |
預設值為 0 的解決方法
使用三元運算子
var originCash = 500; |
總結
var a = 1; |