第3章 基本概念
3.1 語法
ECMAScript 的語法大量借鑒了C 及其他類 C 語言(Java / Perl)的語法。
3.1.1 區分大小寫
ECMAScript 中的一切(變量、函數名、操作符)都區分大小寫。
3.1.2 標識符
標識符——變量、函數、屬性的名字,或函數的參數。標識符可以是按下列各式規則組合起來的一個或多個字符:
1)第一個字符必須是字母、下劃線或美元符號;
2)其他字符可以是字母、下劃線、美元符號或數字。
注:
1)標識符中字母可包含擴展的 ASCII 或 Unicode 字母字符,但不推薦這樣做。
2)駝峰大小寫格式:第一個字母小寫,剩下的每個單詞首字母大寫。 firstSecond
3)關鍵字、保留字、true、false、null不可用作標識符。
3.1.3 注釋
單行注釋://單行注釋
塊級注釋:
/*
*這是一個多行(這兩行的星號不是必須的,純粹為了提高注釋的可讀性,企業級應用中用的較多)
*(塊級)注釋 (這兩行的星號不是必須的,純粹為了提高注釋的可讀性,企業級應用中用的較多)
*/
3.1.4 嚴格模式
嚴格模式為 JavaScript 定義了一種不同的解析和執行模式。
要啟用嚴格模式,可以在頂部添加如下代碼:
‘use strict’—— 編譯指示,用于告訴支持的 JavaScript 引擎切換到嚴格模式。
可以在函數內部上方包含這條編譯指示,也可以制定函數在嚴格模式下執行。
嚴格模式下,JavaScript 的執行結果會有很大不同。
3.1.5 語句
ECMAScript 中的語句以一個分號結尾;若省略分號,由解析器確定語句的結尾(不推薦),代碼行結尾處無分號會導致壓縮錯誤。且加上分號,則解析器不必花時間推測應該在哪里插入分號、增進代碼性能。
3.2 關鍵字和保留字
關鍵字——用于表示控制語句的開始或結束,或用于執行特定操作等。
break do instanceof typeof case else new var catch finally
return void continue for switch while debugger* fuction this
with default if throw delete in try
保留字——無特定用途,但將來可能被用作關鍵字。
avstract enum int short boolean export interface static byte
extends long super char final native synchronized class float
package throws const goto private transient debugger
implements protected volatile double import public
第 5 版 非嚴格模式下運行時的保留字縮減為下列這些:
class enum extends super const export import
嚴格模式下,第5版還對以下保留字施加了限制:
implements package public interface private static let protected yield
3.3 變量
ECMAScript 的變量是松散類型的——可以用來保存任何類型的數據,即每個變量僅僅是一個用于保存值得占位符而已。
如:var message = 'hi'; 變量 message 中保存了一個字符串 hi ,但并不會把它標記為字符串類型。
message = 100;則 message 保存了 一個數值,雖然我們不建議修改變量所保存值得類型,但這種操作在 ECMAScript 中完全有效。
在函數內用 var 定義一個變量,則該變量為定義該變量的作用域中的局部變量,函數推出后則銷毀。
省略 var ,則為全局變量,在函數外的任何地方都可被訪問到(不推薦,難維護,且在嚴格模式下會拋出錯誤)。
注:
ES6 中增加了 let 和 const ,let 用來定義變量,定義后可更改;const 用來定義常量,定義后不可更改。
let 和 var 的區別。
1)let 是塊級作用域,var 是函數級作用域,let 的作用域更小;
2)let 無變量提升。下面定義的變量,在上面使用會報錯;var有變量提升,下面定義的變量,在上面值為undefined。
3)let 同一個變量只能聲明一次,而 var 可聲明多次。
一條語句定義多個變量:
var message = 'hi',
found = false,
age = 29;
注:嚴格模式下,不能定義名為 eval 或 arguments 的變量,否則會導致語法錯誤。
3.4 數據類型
簡單數據類型(基本數據類型): Undefined ; Null ; Boolean ; Number ; String
復雜數據類型:Object,Object 本質上是由一組無序的名值對組成。
3.4.1 typeof 操作符
typeof——返回給定變量的數據類型,可能返回如下字符串:
'undefined'——Undefined
'boolean'——Boolean
'string'——String
'number'——Number
'object'——Object / Null (Null 為空對象的引用)
'function'——Function
typeof 是操作符而非函數,所以可以使用圓括號,也可以不使用。
var message = ’some string‘;
alert(typeof message); / alert(typeof (message));
注:對聲明未初始化的變量和未聲明的變量執行typeof操作符,都會返回 undefined。
各數據類型及描述
-
Undefined:undefined
使用var聲明變量但未初始化;或初始化其值為undefined(不必要,一般不用)
(var message);alert(message);//undefined
-
Null:null
空對象指針,用于在將來保存對象。這樣只要檢查變量是否等于null,就知道這個變量內是否已經保存了一個對象的引用。
alert(null == undefined); //true
alert(null === undefined); //false
-
Boolean:true / false
ECMAScript 中所有類型的值都有與這兩個Boolean 值等價的值;可使用轉型函數Boolean()進行轉換。
非空字符串、非零數值、任何對象都是 true;
空字符串、數值零或NaN、null都是false。
流控制語句(如if)會自動執行 Boolean 轉換。
var message = 'hello';
if(message){alert('value is true');} //message被自動轉換為對應的 Boolean 值(true)。
-
Number
1)定義
var intNum = 55; //整數
八進制:第一位為0,后面數值若超出范圍,則前導零被忽略,將后面數值按十進制解析
var intNum = 070; //八進制的56
var intNum = 079; //無效的八進制數值,解析為79
十六進制:前兩位為0x,后跟十六進制數字。
var initNum = 0xa; //十六進制的10
var initNum = 0x1f; //十六進制的31
2)浮點數值:
必須包含一個小數點,且小數點后必須至少有一位數字。
保存浮點數需要的內存空間是保存整數值的兩倍,所以ECMAScript會不失時機地將浮點數轉換為整數。若小數點后沒有數字(1.)或數字為0(10.0),則將被作為整數來保存。
浮點數最高精度是17位小數,但計算時其精度遠不如整數。如 0.1 + 0.2 不是 0.3,而是0.3000000000000004.因此,永遠不要測試某個特定的浮點數值。
3)數值范圍
由于內存限制,ECMAScript并不能保存世界上所有數值。
Number.MIN_VALUE(5e-324) < number < Number.Max_VALUE(1.7976931348623157e+308)
大于這個范圍,會被轉換為 Infinity(正無窮),小于這個范圍,會被轉換為 -Infinity(負無窮)。
isFinity()可以返回這個數是否在范圍內,在則返回 true,否則返回 false。
4)NaN
非數值——特殊的數值,本該返回數值的操作數未返回數值的情況,不拋出錯誤。
任何涉及 NAN 的操作都會返回 NaN ,NaN 與任何值都不相等。 alert(NaN == NaN ); //false
isNaN(),函數收到一個值后,會嘗試將這個值轉換為數值,可以轉換則返回 false,否則返回 true。
alert(isNaN(true)); 返回 false,因為 true 可以被轉換為1。
5)數值轉換
Number()——用于任何類型;parseInt()、parseFolat()——專用于把字符串轉換為數值。
Number()
var num1 = Number("Hello world!"); //NaN
var num2 = Number(""); //0
var num3 = Number("000011"); //11
var num4 = Number(true); //1
parseInt()
var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(""); // NaN
var num4 = parseInt(22.5); // 22
var num6 = parseInt("70"); // 70
var num8 = parseInt("s2131"); // NaN
var num = parseInt("0xAF", 16); //175
var num1 = parseInt("AF", 16); //175
var num2 = parseInt("AF"); //NaN
指定基數轉換:
var num1 = parseInt("10", 2); //2 (按二進制解析)
var num2 = parseInt("10", 8); //8 (按八進制解析)
var num3 = parseInt("10", 10); //10 (按十進制解析)
var num4 = parseInt("10", 16); //16 (按十六進制解析)
parseFloat()
從第一個字符開始解析,始終忽略前導零
var num1 = parseFloat("1234blue"); //1234 (整數)
var num2 = parseFloat("0xA"); //0
var num3 = parseFloat("22.5"); //22.5
var num4 = parseFloat("22.34.5"); //22.34
var num5 = parseFloat("0908.5"); //908.5
var num6 = parseFloat("3.125e7"); //31250000
-
String
String 類型用于表示由零或多個16 位Unicode 字符組成的字符序列,即字符串。字符串可以由雙
引號(")或單引號(')表示,但前后符號應保持一致。
var firstName = "Nicholas";
var lastName = 'Zakas';
1)特殊的字符字面量(轉義序列),用于表示非打印字符或具有其他用途的字符。一個轉義序列表示一個字符。
任何字符串的長度都可以通過 length 屬性取得。
2)字符串的特點
ECMAScript 中的字符串是不可變的,也就是說,字符串一旦創建,它們的值就不能改變。要改變某個變量保存的字符串,首先要銷毀原來的字符串,然后再用另一個包含新值的字符串填充該變量
3)轉換為字符串 toString()
數值、布爾值、對象和字符串都有一個 toString() 方法,返回一個字符串。null 和 undefined 沒有 toString() 方法。
數值的 toString() 方法可以傳一個參數:輸出數值的基數。
var num = 10;
alert(num.toString()); // "10" 不傳,默認為10
alert(num.toString(2)); // "1010"
alert(num.toString(8)); // "12"
alert(num.toString(10)); // "10"
alert(num.toString(16)); // "a"
在不知道要轉換的值是不是 null 或 undefined 時,可以使用轉型函數 String(),這個函數可以將任何類型的值轉換為字符串。String()遵循下列轉換規則:
如果值有toString()方法,則調用該方法(沒有參數)并返回相應的結果;
如果值是null,則返回"null";
如果值是undefined,則返回"undefined"。
-
Object
ECMAScript 中的對象其實就是一組數據和功能的集合。對象可以通過執行new 操作符后跟要創建
的對象類型的名稱來創建。
如:var o = new Object();若不傳參數,圓括號可省,但不推薦這樣做。
僅僅創建Object 的實例并沒有什么用處,但關鍵是要理解一個重要的思想:即在ECMAScript 中,
Object 類型是所有它的實例的基礎。換句話說,
Object 類型所具有的任何屬性和方法也同樣存在于更具體的對象中。
Object 的每個實例都具有下列屬性和方法。
constructor:保存著用于創建當前對象的函數。對于前面的例子而言,構造函數(constructor)
就是Object()。
hasOwnProperty(propertyName):用于檢查給定的屬性在當前對象實例中(而不是在實例的原型中)是否存在。其中,作為參數的屬性名(propertyName)必須以字符串形式指定(例如:o.hasOwnProperty("name"))。
isPrototypeOf(object):用于檢查傳入的對象是否是傳入對象的原型
propertyIsEnumerable(propertyName):用于檢查給定的屬性是否能夠使用for-in 語句來枚舉。與hasOwnProperty()方法一樣,作為參數的屬性名必須以字符串形式指定。
toLocaleString():返回對象的字符串表示,該字符串與執行環境的地區對應。
toString():返回對象的字符串表示。
valueOf():返回對象的字符串、數值或布爾值表示。通常與toString()方法的返回值相同。
由于在ECMAScript 中Object 是所有對象的基礎,因此所有對象都具有這些基本的屬性和方法。
3.5 操作符
操作符,包括算數操作符、位操作符、關系操作符和相等操作符。
操作符適用于很多值:字符串、數值、布爾值、對象。應用于對象時,相應的操作符通常都會調用對象的 valueOf() 或 toString() 方法,以便取得可以操作的值。
3.5.1 一元操作符——只能操作一個值
1.遞增遞減操作符——可用于數值、字符串、布爾值、對象。
前置:先改變變量的值,在求語句的值
前置遞增: var age = 29;var age2 = 2;var result = ++age + age2;(同 age = age +1;)
//age 為30 result 為32
前置遞減: var age = 29;var age2 = 2;var result = --age+ age2;(同 age = age -1;)
//age 為28 result 為30
后置;先求語句的值,再改變變量的值
后置遞增: var age = 29;var age2 = 2;var result = age++ + age2;(同 age = age +1;)
//age 為30 result 為31
后置遞減: var age = 29;var age2 = 2;var result = age-- + age2;(同 age = age -1;)
//age 為28 result 為31
應用規則:
1)應用于數值時,直接執行加減操作。
2)應用于字符串,若包含有效數字字符,則轉換為數字值,再執行操作,字符串變量變成數值變量;若不包含有效數字字符,則變量的值設為 NaN ,字符串變量變成數值變量。
3)應用于布爾值時,若是 false,則先轉換為 0 再執行;若是 true,則先轉換為 1 再執行;最終都將布爾值變量變為數值變量。
4)應用于對象時,先調用 valueOf() 方法,取得一個可供操作的值,再對其應用上述規則。若結果是 NaN,則調用 toString()方法后再應用上述規則。對象變量變成數值變量。
var s1 = "2";
var s2 = "z";
var b = false;
var f = 1.1;
var o = {
valueOf: function() {
return -1;
}
};
s1++; // 值變成數值3
s2++; // 值變成NaN
b++; // 值變成數值1
f--; // 值變成0.10000000000000009(由于浮點舍入錯誤所致)
o--; // 值變成數值-2
2.一元加減操作符
1)一元加操作符
數值前添加一元加操作符,無作用;
其他類型前添加一元加操作符,會像 Number() 函數一樣對這個值進行轉換。
2)一元減操作符
數值前添加一元減操作符,轉換為對應負數;
其他類型前添加一元減操作符,同樣,會像 Number() 函數一樣對這個值進行轉換,再將得到的值轉換為負數.
var s1 = "01";
var s2 = "1.1";
var s3 = "z";
var b = false;
var f = 1.1;
var o = {
valueOf: function() {
return -1;
}
};
s1 = -s1; // 值變成了數值-1
s2 = -s2; // 值變成了數值-1.1
s3 = -s3; // 值變成了NaN
b = -b; // 值變成了數值0
f = -f; // 變成了-1.1
o = -o; // 值變成了數值1
3.5.2 位操作符 略
3.5.3 布爾操作符——與、或、非
1.邏輯非 —— !
空字符串、數值0、null、undefined、null、NaN 的布爾值為 false,則對他們執行邏輯非操作,返回 true。
alert(!false); // true
alert(!"blue"); // false
alert(!0); // true
alert(!NaN); // true
alert(!""); // true
aler t(!12345); // false
2.邏輯與 —— && 有兩個操作數
真值表如下:
邏輯與操作可以應用于任何類型的操作數,而不僅僅是布爾值。在有一個操作數不是布爾值的情況下,邏輯與操作就不一定返回布爾值;此時,它遵循下列規則:
如果第一個操作數的布爾值是 true,則返回第二個操作數;
如果有一個操作數是null,則返回null;
如果有一個操作數是NaN,則返回NaN;
如果有一個操作數是undefined,則返回undefined。
邏輯與操作符是短路操作符,如果第一個操作數為 false,則結果都為 false,第二個操作數不執行。
3.邏輯或 —— || 有兩個操作數
真值表如下:
與邏輯與操作相似,如果有一個操作數不是布爾值,邏輯或也不一定返回布爾值;此時,它遵循下列規則:
如果第一個操作數的求值結果為 true,則返回第一個操作數;
如果第一個操作數的求值結果為 false,則返回第二個操作數;
如果兩個操作數都是null,則返回null;
如果兩個操作數都是NaN,則返回NaN;
如果兩個操作數都是undefined,則返回undefined。
邏輯或操作符也是短路操作符,如果第一個操作數為 true,則結果都為 true,第二個操作數不執行。
3.5.4 乘性操作符
乘法、除法、求模
如果參與乘性操作符的某個操作數不是數值,后臺會先使用 Number() 轉型函數將其轉換為數值。
1.乘法 *
特殊值處理規則:
? 如果操作數都是數值,執行常規的乘法計算,即兩個正數或兩個負數相乘的結果還是正數,而 如果只有一個操作數有符號,那么結果就是負數。如果乘積超過了 ECMAScript數值的表示范圍, 則返回 Infinity 或-Infinity;
? 如果有一個操作數是 NaN,則結果是 NaN;
? 如果是 Infinity 與 0相乘,則結果是 NaN;
? 如果是 Infinity 與非 0數值相乘,則結果是 Infinity 或-Infinity,取決于有符號操作數 的符號;
? 如果是 Infinity 與 Infinity 相乘,則結果是 Infinity;
? 如果有一個操作數不是數值,則在后臺調用 Number()將其轉換為數值,然后再應用上面的 規則
2.除法 /
特殊值處理規則:
? 如果操作數都是數值,執行常規的除法計算,即兩個正數或兩個負數相除的結果還是正數,而 如果只有一個操作數有符號,那么結果就是負數。如果商超過了 ECMAScript數值的表示范圍, 則返回 Infinity 或-Infinity;
? 如果有一個操作數是 NaN,則結果是 NaN;
? 如果是 Infinity 被 Infinity 除,則結果是 NaN;
? 如果是零被零除,則結果是 NaN;
? 如果是非零的有限數被零除,則結果是 Infinity 或-Infinity,取決于有符號操作數的符號;
? 如果是 Infinity 被任何非零數值除,則結果是 Infinity 或-Infinity,取決于有符號操作 數的符號;
? 如果有一個操作數不是數值,則在后臺調用 Number()將其轉換為數值,然后再應用上面的規則。
3.求模(余數) %
特殊值處理規則:
? 如果操作數都是數值,執行常規的除法計算,返回除得的余數;
? 如果被除數是無窮大值而除數是有限大的數值,則結果是 NaN;
? 如果被除數是有限大的數值而除數是零,則結果是 NaN;
? 如果是 Infinity 被 Infinity 除,則結果是 NaN;
? 如果被除數是有限大的數值而除數是無窮大的數值,則結果是被除數;
? 如果被除數是零,則結果是零;
? 如果有一個操作數不是數值,則在后臺調用 Number()將其轉換為數值,然后再應用上面的規則。
3.5.5 加性操作符:加法、減法
1.加法
操作數為如下類型時,處理如下:
數值:做加法
字符串:將字符串拼接,只有一個是字符串,則將另一個也轉換為字符串。
對象、數值、布爾值、null、undefined:調用 toString() 取得相應字符串值,再拼接。
2.減法
操作數為如下類型時,處理如下:
數值:做減法
如果有一個操作數是字符串、布爾值、null、undefined:后臺先調用 Number() 函數將其轉換為數值,再進行減法。如果轉換的結果是 NaN,則減法的結果是 NaN;
如果有一個操作數是對象,則調用 valueOf() 方法取得表示該對象的數值。得到的是 NaN,則減法的結果就是 NaN。如果沒有valueOf()方法,則調用其 toString() 方法并將得到的字符串轉換為數值。
3.5.6 關系操作符
小于(<)、大于(>)、小于等于(<=)和大于等于(>=)
執行規則:
兩個都是數值:執行數值比較
兩個都是字符串:比較兩個字符串對應的字符編碼值
如果一個是數值:則將另一個操作數轉換為數值,然后執行數值比較
如果一個操作數是對象,則調用這個對象的 valueOf()方法,用得到的結果按照前面的規則執 行比較。如果對象沒有valueOf()方法,則調用 toString()方法,并用得到的結果根據前面 的規則執行比較。
如果一個操作數是布爾值,則先將其轉換為數值,然后再執行比較。
3.5.7 相等操作符
1. 相等和不相等 == / !=
先強制轉型,再比較是否相等
特殊情況及比較結果:
2. 全等和不全等 === /!==
只在兩個操作蘇未經轉換就相等的情況下返回 true,即類型和值均相等。
3.5.8 條件操作符
var max = (num1 > num2) ? num1 : num2;
在這個例子中,max 中將會保存一個大的值。這個表達式的意思是:如果 num1 大于 num2(關 系表達式返回 true),則將 num1 的值賦給 max;如果 num1 小于或等于 num2(關系表達式返回 false), 則將 num2 的值賦給 max。
3.5.9 賦值操作符
var num = 10 ; 將等號右側的值賦給左側變量。
復合操作符:
num += 10; 即為 num = num + 10 ;
同理還有:
? 乘/賦值(*=); ? 除/賦值(/=); ? 模/賦值(%=); ? 加/賦值(+=); ? 減/賦值(-=); ? 左移/賦值(<<=); ? 有符號右移/賦值(>>=);無符號右移/賦值(>>>=)。
3.5.10 逗號操作符
使用逗號操作符可以在一條語句中執行多個操作,如:
var num1=1, num2=2, num3=3; //聲明多個變量。
var num = (5, 1, 4, 8, 0); // 賦值 : num 的值為 0