本章內容
- 語法
- 數(shù)據(jù)類型
- 流控制語句
- 理解函數(shù)
3.1 語法
3.1.1 區(qū)分大小寫
區(qū)分大小寫
3.1.2 標識符
- 第一個字符必須是一個字母囚聚、下劃線(_)或1一個美元符號($);
- 其他字符可以是字母、下劃線、美元符號或數(shù)字。
按照慣例,ECMAScript 標識符采用駝峰大小寫格式起惕。
3.1.3 注釋
// 單行注釋
/*
這是一個多行(塊級)注釋
*/
3.1.4 嚴格模式
"use strict";
function doSomething () {
"use strict";
//函數(shù)體
}
3.1.5 語句
ECMAScript中的語句以一個分號結尾。
var sum = a + b
var diff = a - b;
雖然語句結尾的分號不是必需的咏删,但我們建議任何時候都不要省略它惹想。
最佳實踐是始終在控制語句中使用代碼塊
if (test) {
alert(test);
}
3.2 關鍵字和保留字
3.3 變量
var message;
var message = "hi";
var message = "hi";
message = 100; //有效,但不推薦
function test () {
var message = "hi"; // 局部變量
}
test();
alert(message); // 錯誤督函!
3.4 數(shù)據(jù)類型
ECMAScript 中有5種基本數(shù)據(jù)類型:Undefined
嘀粱、Null
、Boolean
辰狡、Number
和String
锋叨。還有一種復雜數(shù)據(jù)類型——Object
。
3.4.1 typeof 操作符
對于一個值使用typeof
操作符可能返回下列某個字符串:
- "undefined"——如果這個值未定義
- "boolean"——如果這個值是布爾值
- "string"——如果這個值是字符串
- "number"——如果這個值是數(shù)值
- “object”——如果這個值是對象或null
- "function"——如果這個值是函數(shù)
var message = "some string";
alert(typeof message); // "string"
alert(typeof(message)); // "string"
alert(typeof 95); // "number"
注意宛篇,typeof
是一個操作符而不是函數(shù)娃磺,因此例子中的圓括號不是必需的。
3.4.2 Undefined 類型
Undefined
類型只有一個值叫倍,即特殊的 undefined
偷卧。
var message;
alert(message == undefined); //true
var message;
// 下面這個變量未聲明
// var age
alert(message); // "undefined"
alert(age); // 產(chǎn)生錯誤
var message
// var age
alert(typeof message); // "undefined"
alert(typeof age); // "undefined"
3.4.3 Null 類型
只有一個值null
豺瘤。
var car = null;
alert(typeof car); // "object"
如果定義的變量準備在將來用于保存對象,那么最好將該變量初始化為null
而不是其他值涯冠。
if (car != null) {
// 對 car 對象執(zhí)行某些操作
}
實際上炉奴,undefined
值是派生自null
值的。
alert(null == undefined); //true
沒有必要把一個變量的值顯式地設置為undefined
蛇更。
只要意在保存對象的變量還沒有真正保持隊形瞻赶,就應該明確保存null
值。
3.4.4 Boolean 類型
var found = true;
var lost = false;
True
和False
都不是Boolean
值派任,只是標識符砸逊。
ECMAScript中所有類型的值都有與這兩個Boolean
值等價的值,可以調用轉型函數(shù)Boolean()
掌逛。
var message = "Hello world!";
var messageAsBoolean = Boolean(message);
數(shù)據(jù)類型 | 轉換為true的值 | 轉換為false的值 |
---|---|---|
Boolean | true | false |
String | 任何非空字符串 | 空字符串 |
Number | 任何非零數(shù)字值 | 0和NaN |
Object | 任何對象 | null |
Undefined | n/a (不適用) | undefined |
var message = "Hello world";
if (message) {
alert("Value is true");
}
3.4.5 Number 類型
var intNum = 55;
八進制字面值的第一位必須是0
师逸。八進制字面量在嚴格模式下是無效的。
var octalNum1 = 070; //八進制的56
var octalNum2 = 079;
var octalNum3 = 08; //無效的八進制數(shù)值——解析為8
十六進制字面值的前兩位必須是 0x
豆混。
var hexNum1 = 0xA; //十六進制的10
var hexNum2 = 0xlf; //十六進制的31
在進行算術計算時篓像,所有以八進制和十六進制表示的數(shù)值最終都將被轉換成十進制數(shù)值。
1.浮點數(shù)值
var floatNum1 = 1.1;
var floatNum2 = 0.1;
var floatNum3 = .1; //有效皿伺,但不推薦
var floatNum1 = 1.; //小數(shù)點后面沒有數(shù)字——解析為1
var floatNum2 = 10.0; //整數(shù)——解析為10
var floatNum = 3.125e7; //等于31250000
在默認情況下员辩,ECMAScript會將那些小數(shù)點后面帶有6個零以上的浮點數(shù)值轉換為以e表示法表示的數(shù)值(0.0000003會被轉換成3e-7)。
浮點數(shù)值的最高精度是17位小數(shù)鸵鸥,但在進行算術計算時其精確度遠遠不如整數(shù)奠滑。例如,0.1加0.2結果不是0.3妒穴,而是0.30000000000000004宋税。
2.數(shù)值范圍
計算結果得到一個超出JavaScript數(shù)值范圍的值,那么這個數(shù)值將被自動轉換成特殊的Infinity
值讼油。負數(shù)會被轉換成-Infinity
杰赛,正數(shù)會被轉換成Infinity
。
var result = Number.MAX_VALUE + Number.MAX_VALUE;
alert(isFinite(result)); //false
3.NaN
這個數(shù)值用于表示一個本來要返回數(shù)值的操作數(shù)未返回數(shù)值的情況(這樣就不會拋出錯誤了)矮台。在ECMAScript中淆攻,任何數(shù)值除以0會返回NaN
,不會影響其他代碼的執(zhí)行嘿架。
任何涉及NaN
的操作都會返回NaN
瓶珊,這個特點在多步計算中有可能導致問題。
NaN
與任何值都不想等耸彪,包括NaN
本身伞芹。
alert(NaN == NaN); //false
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false
alert(isNaN("10")); //false
alert(isNaN("blue")); //true(不能轉換成數(shù)值)
alert(isNaN(true)); //false(可以被轉換成數(shù)值1)
4.數(shù)值轉換
有3個函數(shù)可以把非數(shù)值轉換為數(shù)值:Number()
、parseInt()
和parseFloat()
碱蒙。
Number()
函數(shù)的轉換規(guī)則如下偿警。
- 如果是
Boolean
值锅风,true
和false
將被轉換為1
和0
稿静。 - 如果是數(shù)字值,只是簡單的傳入和返回呢岗。
- 如果是
null
值评汰,返回0
读拆。 - 如果是
undefined
汉形,返回NaN
纸镊。 - 如果是字符串,遵循下列規(guī)則:
如果是字符串中只包含數(shù)字概疆,則將其轉換為十進制數(shù)值逗威;(忽略前導零)
如果字符串中包含有效的浮點格式,則將其轉換為對應的浮點數(shù)值岔冀;(忽略前導0)
如果字符串中包含有效的十六進制格式凯旭,則將其轉換為相同大小的十進制整數(shù)值;
如果字符串是空的使套,則將其轉換為0
罐呼;
如果字符串中包含除上述格式之外的字符,則將其轉換為NaN
侦高。 - 如果是對象弄贿,則調用對象的
valueOf()
方法,然后依照前面的規(guī)則轉換返回的值矫膨。如果轉換的結果是NaN
,則調用對象的toString()
期奔,然后再次依照前面的規(guī)則轉換返回的字符串值侧馅。
var num1 = Number("Hello world!"); //NaN
var num2 = Number(""); //0
var num3 = Number("000011"); //11
var num4 = Number(true); //1
一元操作符的操作與Number()函數(shù)相同
parseInt()
函數(shù)在轉換字符串時,更多的是看其是否符合數(shù)值模式呐萌。它會忽略字符串前面的空格馁痴,直至找到第一個非空格字符。如果第一個字符不是數(shù)字字符或者負號肺孤,會返回NaN
罗晕;如果第一個字符是數(shù)字字符,會繼續(xù)解析赠堵,知道解析完所有后需字符或遇到一個非數(shù)字字符小渊。
var num1 = parseInt("1234blue1213"); //1234
var num2 = parseInt(""); //NaN
var num3 = parseInt("0xA"); //10 (十六進制數(shù))
var num4 = parseInt(22.5); //22
var num = parseInt("0xAF", 16); //175
var num = parseInt("AF", 16); //175
var num2 = parseInt("AF"); //NaN
parseFloat
也是從第一個字符開始解析每個字符。一直解析到字符串末尾茫叭,或者解析到遇見一個無效的浮點數(shù)字字符為止酬屉。
始終都會忽略前導的零。只解析十進制值。
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.12e7"); //31250000
3.4.6 String 類型
var firstName = "Nicholas";
var lastName = 'Zakas';
1.字符字面量
String
數(shù)據(jù)類型包含一些特殊的字符字面量呐萨,也叫轉義序列杀饵。
2.字符串的特點
要改變某個變量保存的字符串,首先要銷毀原來的字符串谬擦,然后再用另一個包含新值的字符串填充該變量切距。
var lang = "Java";
lang =lang + "Script";
3.轉換為字符串
把一個值轉換為一個字符串有兩種方式。第一種是使用幾乎每個值都有的toString()
方法惨远。這個方法唯一要做的就是返回相應值得字符串表現(xiàn)谜悟。
var age =11;
var ageAsString = age.toString(); //字符串“11”
var found = true;
var foundAsString = found.toString(); //字符串”true“
數(shù)值、布爾值锨络、對象和字符串值都有toString()
方法赌躺。但null
和undefined
值沒有這個方法。
toString()
可以輸出以二進制羡儿、八進制礼患、十六進制,乃至其他任意有效進制格式標識的字符串值掠归。
var num = 10;
alert (num.toString()); //"10"
alert (num.toString(2)); //"1010"
alert (num.toString(8)); //"12"
alert (num.toString(10)); //"10"
alert (num.toString(10)); //"a"
在不知道要轉換的值是不是null
和undefined
的情況下缅叠,還可以使用轉型函數(shù)String()
,這個函數(shù)能將任何類型的值轉換為字符串。
- 如果值有
toString()
方法虏冻,則調用該方法(沒有參數(shù))并返回相應的結果肤粱; - 如果值是
null
,則返回”null“厨相; - 如果值是
undefined
领曼,則返回”undefined“。
3.4.7 Object 類型
ECMAScript中的對象其實就是一組數(shù)據(jù)和功能的集合蛮穿。
var o = new Object();
var o = new Object;//有效庶骄,但不推薦省略圓括號
Object
的每個實例都具有下列屬性和方法。
-
Constructor
:保存著用于創(chuàng)建當前對象的函數(shù)践磅。對于前面的例子而言单刁,構造函數(shù)就是Object()
。 -
hasOwnProperty(propertyName)
:用于檢查給定的屬性在當前對象實例中是否存在府适。其中羔飞,作為參數(shù)的屬性名必須以字符串形式指定。 -
isPrototypeOf(object)
:用于檢查傳入的對象是否是另一個對象的原型檐春。 -
propertyIsEnumerable(propertyName)
:用于檢查給定的屬性是否能夠使用for-in
語句來枚舉逻淌。作為參數(shù)的屬性名必須以字符串形式指定。 -
toLocaleString()
:返回對象的字符串表示疟暖,該字符串與執(zhí)行環(huán)境的地區(qū)對應恍风。 -
toString()
:返回對象的字符串表示。 -
valueOf()
:返回對象的字符串、數(shù)值或布爾值表示朋贬。通常與toString()
方法的返回值相同凯楔。
由于在ECMAScript中Object
是所有對象的基礎,因此所有對象都具有這些基本的屬性和方法锦募。
3.5 操作符
ECMAScript 操作符的與眾不同之處在于摆屯,它們能夠適用于很多值,例如字符串糠亩、數(shù)字值虐骑、布爾值,甚至對象赎线。在應用于對象時廷没,相應的操作符通常都會調用對象的valueOf()
和(或)toString()
方法,以便取的可以操作的值垂寥。
3.5.1 一元操作符
1.遞增和遞減操作符
var age = 29;
++age;
var age = 29;
--age;
執(zhí)行前置遞增和遞減操作時颠黎,變量的值都是在語句被求值以前改變的。
var age = 29;
var anotherAge = --age + 2;
alert(age); //輸出28
alert(anotherAge); //輸出30
后置型遞增和遞減操作是在包含它們的語句被求值之后才執(zhí)行的滞项。
var num1 = 2;
var num2 = 20;
var num3 = num1-- + num2; //等于22
var num4 = num1 + num2; //等于21
在應用于不同的值時狭归,遞增和遞減操作符遵循下列規(guī)則。
- 在應用與一個包含有效數(shù)字字符的字符串時文判,先將其轉換為數(shù)字值过椎,在執(zhí)行加減1的操作。字符串變量變成數(shù)值變量戏仓。
- 在應用于一個不包含有效數(shù)字字符的字符串時疚宇,將變量的值設置為
NaN
。字符串變量變成數(shù)值變量赏殃。 - 在應用于布爾值
false
時敷待,先將其轉換為0再執(zhí)行加減1的操作。布爾值變量變成數(shù)值變量嗓奢。 - 在應用于布爾值
true
時,先將其轉換為1在執(zhí)行加減1的操作浑厚。布爾值變量變成數(shù)值變量股耽。 - 在應用于浮點數(shù)值時,執(zhí)行加減1的操作钳幅。
- 在應用于對象時物蝙,先調用對象的
valueOf()
方法以取得一個可供操作的值。然后對該值應用前述規(guī)則敢艰。如果結果是NaN
诬乞,則在調用toString()
方法后再應用前述規(guī)則。對象變量變成數(shù)值變量。
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.一元加和減操作符
一元操作符以一個加號表示震嫉,放在數(shù)值前面森瘪,對數(shù)值不會產(chǎn)生任何影響。
var num = 25;
num = +num; //25
不過票堵,在對非數(shù)值應用一元加操作符時扼睬,該操作符會像Number()
轉型函數(shù)一樣對這個值執(zhí)行轉換。
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
一元減操作符主要用于表示負數(shù)悴势。
var num = 25;
num = -num; //-25
應用于飛數(shù)值時窗宇,一元減操作符遵循與一元加操作符相同的規(guī)則,最后再將得到的數(shù)值轉換為負數(shù)特纤。
3.5.2 位操作符
在 ECMAScript中军俊,當對數(shù)值應用位操作符時,后臺會發(fā)生如下轉換過程:64位的數(shù)值被轉換成32位數(shù)值捧存,然后執(zhí)行位操作粪躬,最后再將32位的結果轉換回64位數(shù)值。這個轉換過程導致了一個嚴重的副效應矗蕊,即在對特殊的NaN
和Infinity
值應用位操作時短蜕,這兩個值都會被當成0來處理。
如果對非數(shù)值應用位操作符傻咖,會先使用Number()
函數(shù)將該值轉換為一個數(shù)值朋魔,然后再應用位操作。得到的結果將是一個數(shù)值卿操。
1.按位非 (NOT)
var num1 = 25; //二進制
var num2 = ~num1; //二進制
alert(num2); //-26
這也驗證了按位非操作的本質:操作數(shù)的負值減1警检。
2.按位與(AND)
從本質上講,按位與操作就是將兩個數(shù)值的每一位對齊害淤,然后根據(jù)下表中的規(guī)則扇雕,對相同位置上的兩個數(shù)執(zhí)行AND操作:
第一個數(shù)值的位 | 第二個數(shù)值的位 | 結果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
var result = 25 & 3;
alert(result); // 1
3.按位或 (OR)
按位或操作遵循下面這個真值表。
第一個數(shù)值的位 | 第二個數(shù)值的位 | 結果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
var result = 25 | 3;
alert(result); //27
4.按位異或 (XOR)
按位異或操作符由一個插入符號(^)表示窥摄,也有倆操作數(shù)镶奉。以下是按位異或的真值表。
第一個數(shù)值的位 | 第二個數(shù)值的位 | 結果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
var result = 25 ^ 3;
alert (result); //26
5.左移
左移操作符由兩個小于號(<<)表示崭放,這個操作符會將數(shù)值的所有位向左移動指定的位數(shù)哨苛。
var oldValue = 2; //等于二進制的10
var newValue = oldValue << 5; //等于二進制的1000000,十進制的64
左移操作會以0來填充這些空位币砂,以便得到的結果是一個完整的32位二進制數(shù)建峭。
注意,左移不會影響操作數(shù)的符號位决摧。換句話說亿蒸,如果將-2向左移動5位凑兰,結果將是-64,而非64边锁。
6.有符號的右移
有符號的右移操作符由兩個大于號(>>)表示姑食,這個操作符會將數(shù)值向右移動,但保留符號位砚蓬。
var oldValue = 64; //等于二進制的1000000
var newValue = oldValue >> 5; //等于二進制的10矢门,即十進制的2
7.無符號右移
無符號右移操作符由3個大于號(>>>)表示。這個操作符會將數(shù)值的所有32位都向右移動灰蛙。對正數(shù)來說祟剔,無符號右移結果與有符號右移相同。
var oldValue = 64;
var newValue = oldValue >>> 5; //等于二進制的10摩梧,即十進制的2
對負數(shù)來說物延,無符號右移是以0來填充空位,不會保留符號位的值仅父。
var oldValue = -64;
var newValue = oldValue >>> 5; //等于十進制的134217726
3.5.3 布爾操作符
布爾操作符一共有3個:非(NOT)叛薯、與(AND)和或(OR)。
1.邏輯非
邏輯非操作符由一個嘆號(s舷恕)表示耗溜,可以應用于ECMAScript中的任何值。邏輯非操作符首先會將它的操作數(shù)轉換為一個布爾值省容,然后再對其求反抖拴。邏輯非操作符遵循下列規(guī)則:
- 如果操作數(shù)是一個對象,返回
fasle
腥椒; - 如果操作數(shù)是一個空字符串阿宅,返回
true
; - 如果操作數(shù)是一個非空字符串笼蛛,返回
false
洒放; - 如果操作數(shù)是數(shù)值0,返回
true
滨砍; - 如果操作數(shù)是任意非0數(shù)值(包括Infinity)往湿,返回
false
; - 如果操作數(shù)是
null
惋戏,返回true
; - 如果操作數(shù)是
NaN
领追,返回true
; - 如果操作數(shù)是
undefined
日川,返回true
蔓腐。
alert(!false); //true
alert(!"blue"); //false
alert(!0); //true
alert(!NaN); //true
alert(!""); //true
alert(!12345); //false
邏輯非操作符也可以用于將一個值轉換為與其對應的布爾值矩乐。而同時使用兩個邏輯非操作符龄句,實際上就會模擬Boolean()
轉型函數(shù)的行為回论。
alert(!!"blue"); //true
alert(!!0); //false
alert(!!NaN); //false
alert(!!""); //false
alert(!!12345); //true
2.邏輯與
邏輯與操作符由兩個和號(&&)表示,有兩個操作數(shù)分歇,如下面的例子所示:
var result = true && false;
邏輯與的真值表如下:
第一個操作數(shù) | 第一個操作數(shù) | 結果 |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
邏輯與操作可以應用于任何類型的操作數(shù)傀蓉,而不僅僅是布爾值。在有一個操作數(shù)不是布爾值的情況下职抡,邏輯與操作就不一定返回布爾值葬燎;此時,他遵循下列規(guī)則:
- 如果第一個操作數(shù)是對象缚甩,則返回第二個操作數(shù)谱净;
- 如果第二個操作數(shù)是對象,則只有在第一個操作數(shù)的求值結果為
true
的情況下才會返回該對象擅威; - 如果兩個操作數(shù)都是對象壕探, 則返回第二個操作數(shù);
- 如果有一個操作數(shù)是
NaN
郊丛,則返回NaN
; - 如果有一個操作數(shù)是
undefined
李请,則返回undefined
。
邏輯與操作術語短路操作厉熟,即如果第一個操作數(shù)能夠決定結果导盅,那么就不會再對第二個操作數(shù)求值。如果第一個操作數(shù)是false
, 則無論第二個操作數(shù)是什么值揍瑟,結果都不會是true
了白翻。
var found = true;
var result = (found && someUndefinedVariable); //這里會發(fā)生錯誤
alert(result); //這一行不會執(zhí)行
var found = false;
var result = (found && someUndefinedVariable); //不會發(fā)生錯誤
alert(result); //會執(zhí)行("false")
3.邏輯或
邏輯或操作符由兩個豎線符號(||)表示,由兩個操作數(shù)月培。
var result = true || false;
邏輯或的真值表如下:
第一個操作數(shù) | 第二個操作數(shù) | 結果 |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
如果有一個操作數(shù)不是布爾值嘁字,邏輯或也不一定返回布爾值;此時杉畜,它遵循下列規(guī)則:
- 如果第一個操作數(shù)是對象纪蜒,則返回第一個操作數(shù);
- 如果第一個操作數(shù)的求值結果為
false
此叠,則返回第二個操作數(shù)纯续; - 如果兩個操作數(shù)都是對象,則返回第一個操作數(shù)灭袁;
- 如果兩個操作數(shù)都是
null
猬错,則返回null
; - 如果兩個操作數(shù)都是
NaN
,則返回NaN
茸歧; - 如果兩個操作數(shù)都是
undefined
倦炒,則返回undefined
。
邏輯或操作符也是短路操作符软瞎。也就是說逢唤,如果第一個操作數(shù)的求值結果為true
,就不會對第二個操作數(shù)求值了拉讯。
var found = true;
var result = (found || someUndefinedVariable); //不會發(fā)生錯誤
alert(result); //會執(zhí)行 ("true")
var found = false;
var result = (found || someUndefinedVariable); //這里會發(fā)生錯誤
alert(result); //這一行不會執(zhí)行
我們可以利用邏輯或的這一行為來避免為變量賦null
或undefined
值。例如:
var myObject = preferredObject || backupObject;
3.5.4 乘性操作符
ECMAScript定義了3個乘性操作符:乘法鳖藕、除法和求模魔慷。如果參與乘法計算的某個操作數(shù)不是數(shù)值,后臺會先使用Number()
轉型函數(shù)將其轉換為數(shù)值著恩。也就是說院尔,空字符串將被當作0,布爾值true
將被當作1喉誊。
1.乘法
乘法操作符由一個星號(*)表示邀摆,用于計算兩個數(shù)值的乘積。
var result = 34 * 56;
在處理特殊值的情況下伍茄,乘法操作符遵循下列特殊的規(guī)則:
- 如果操作數(shù)都是數(shù)值隧熙,執(zhí)行常規(guī)的乘法計算。如果乘積超過了ECMAScript數(shù)值的表示范圍幻林,則返回
Infinity
或-Infinity
贞盯; - 如果有一個操作數(shù)是
NaN
,則結果是NaN
; - 如果是
Infinity
與0相乘沪饺,則結果是NaN
躏敢; - 如果是
Infinity
與非0數(shù)值相乘,則結果是Infinity
或-Infinity
整葡,取決于有符號操作數(shù)的符號件余; - 如果有一個操作數(shù)不是數(shù)值,則在后臺調用
Number()
將其轉換為數(shù)值遭居,然后再應用上面的規(guī)則啼器。
2.除法
除法操作符由一個斜線符號(/)表示,執(zhí)行第二個操作數(shù)除第一個操作數(shù)的計算俱萍,如下面的例子所示:
var result = 66 / 11;
規(guī)則如下:
- 如果操作數(shù)都是數(shù)值端壳,執(zhí)行常規(guī)的除法計算。如果商超過了ECMAScript數(shù)值的表示范圍枪蘑,則返回
Infinity
或-Infinity
损谦; - 如果有一個操作數(shù)是
NaN
,則結果是NaN
; - 如果是
Infinity
被Infinity
除,則結果是NaN
岳颇; - 如果是零被零出照捡,則結果是
NaN
; - 如果是非零的有限數(shù)被零除话侧,則結果是
Infinity
或-Infinity
栗精; - 如果是
Infinity
被任何非零數(shù)值除,則結果是Infinity
或-Infinity
瞻鹏; - 如果有一個操作數(shù)不是數(shù)值悲立,則在后臺調用
Number()
將其轉換為數(shù)值赢赊,然后在應用上面的規(guī)則。
3.求模
求模(余數(shù))操作符由一個百分號(%)表示级历,用法如下:
var result = 26 % 5; //等于1
求模操作符會遵循下列特殊規(guī)則來處理特殊的值:
- 如果操作數(shù)都是數(shù)值,執(zhí)行常規(guī)的除法計算叭披,返回除得的余數(shù)寥殖;
- 如果被除數(shù)是無窮大值而除數(shù)是有限大的數(shù)值,則結果是
NaN
涩蜘; - 如果被除數(shù)是有限大的數(shù)值而除數(shù)是零嚼贡,則結果是
NaN
; - 如果是
Infinity
被Infinity
除同诫,則結果是被除數(shù)
粤策; - 如果被除數(shù)是有限大的數(shù)值而除數(shù)是無窮大的數(shù)值,則結果是被除數(shù)误窖;
- 如果被除數(shù)是零叮盘,則結果是零;
- 如果有一個操作數(shù)不是數(shù)值霹俺,則在后臺調用
Number()
將其轉化為數(shù)值柔吼,然后在應用上面的規(guī)則。
3.5.5 加性操作符
在ECMAScript中丙唧,這兩個操作符有一系列的特殊行為愈魏。
1.加法
var result = 1 + 2;
如果兩個操作符都是數(shù)值,執(zhí)行常規(guī)的加法計算想际,然后根據(jù)下列規(guī)則返回結果:
- 如果有一個操作數(shù)是
NaN
,則結果是NaN
培漏; - 如果是
Infinity
加Infinity
,則結果是Infinity
胡本; - 如果是
-Infinity
加-Infinity
牌柄,則結果是-Infinity
; - 如果是+0加+0侧甫,則結果是+0友鼻;
- 如果是-0加-0,則結果是-0闺骚;
- 如果是+0加-0彩扔,則結果是+0;
不過僻爽,如果有一個操作數(shù)是字符串虫碉,那么就要應用如下規(guī)則:
- 如果兩個操作數(shù)都是字符串,則將第二個操作數(shù)與第一個操作數(shù)拼接起來胸梆;
- 如果只有一個操作數(shù)是字符串敦捧,則將另一個操作數(shù)轉換為字符串须板,然后再將兩個字符串拼接起來。
如果有一個操作數(shù)是對象兢卵、數(shù)值或布爾值习瑰,則調用它們的toString()
方法取得相應的字符串值,然后再應用前面關于字符串的規(guī)則秽荤。對于undefined
和null
甜奄,則分別調用String()
函數(shù)并取得字符串"undefined"和"null"。
var result1 = 5 + 5; //連個數(shù)值相加
alert(result1); //10
var result2 = 5 + "5"; //一個數(shù)值和一個字符串相加
alert(result2); //"55"
var num1 =5;
var num2 =10;
var message = "The sum of 5 and 10 is" + num1 + num2;
alert(message); //"The sum of 5 and 10 is 510"
var num1 = 5;
var num2 = 10;
var message = "The sum of 5 and 10 is" + (num1 + num2);
alert(message); //"The sum of 5 and 10 is 15"
2.減法
var result = 2 - 1;
同樣需要遵循一些特殊規(guī)則窃款,如下所示:
- 如果兩個操作符都是數(shù)值课兄,則執(zhí)行常規(guī)的算術減法操作并返回結果;
- 如果有一個操作數(shù)是
NaN
晨继,則結果是NaN
烟阐; - 如果是
Infinity
減Infinity
,則結果是NaN
紊扬; - 如果是
-Infinity
減-Infinity
蜒茄,則結果是NaN
; - 如果是
Infinity
減-Infinity
餐屎,則結果是Infinity
扩淀; - 如果是
-Infinity
減Infinity
,則結果是-Infinity
啤挎; - 如果是+0減+0驻谆,則結果是+0;
- 如果是+0減-0庆聘,則結果是-0胜臊;
- 如果是-0減-0火欧,則結果是+0燥翅;
- 如果有一個操作數(shù)是字符串、布爾值叶圃、
null
或undefined
宴抚,則先在后臺調用Number()
函數(shù)將其轉換為數(shù)值勒魔,然后再根據(jù)前面的規(guī)則執(zhí)行減法計算。如果轉換的結果是NaN
菇曲,則減法的結果就是NaN
冠绢; - 如果有一個操作符是對象,則調用對象的
valueOf()
方法以取得表示該對象的數(shù)值常潮。如果得到的值是NaN
弟胀,則減法的結果就是NaN
。如果對象沒有valueOf()
方法,則調用其toString()
方法并將得到的字符串轉換為數(shù)值孵户。
var result1 = 5 - true; //4
var result2 = NaN - 1; //NaN
var result3 = 5 - 3; //2
var result4 = 5 - ""; //5
var result5 = 5 - "2"; //3
var result6 = 5 - null; //5
3.5.6 關系操作符
小于(<)萧朝、大于(>)、小于等于(<=)和大于等于(>=)這幾個關系操作符用于對兩個值進行比較夏哭,這幾個操作符都返回一個布爾值检柬。
var result1 = 5 > 3; //true
var result2 = 5 < 3; //false
當關系操作符的操作數(shù)使用了非數(shù)值時,也要進行數(shù)據(jù)轉換或完成某些奇怪的操作竖配。
- 如果連個操作數(shù)都是數(shù)值何址,則執(zhí)行數(shù)值比較。
- 如果兩個操作數(shù)都是字符串械念,則比較兩個字符串對應的字符編碼值。
- 如果一個操作數(shù)是數(shù)值运悲,則將一個操作數(shù)轉換為一個數(shù)值龄减,然偶執(zhí)行數(shù)值比較。
- 如果一個操作數(shù)是對象班眯,則調用這個對象的
valueOf()
方法希停,用得到的結果按照前面的規(guī)則執(zhí)行比較。如果對象沒有valueOf()
方法署隘,則調用toString
方法宠能,并用得到的結果根據(jù)前面的規(guī)則執(zhí)行比較。 - 如果一個操作數(shù)是布爾值磁餐,則先將其轉換為數(shù)值违崇,然后在執(zhí)行比較。
在使用關系操作符比較兩個字符串時诊霹,會執(zhí)行一種奇怪的操作羞延。很多人都會認為,在比較字符串值時脾还,小于的意思是“在字母表中的位置靠前”伴箩,而大于則意味著“在字母表中的位置靠后”,但實際上完全不是那么回事鄙漏。在比較字符串時嗤谚,實際比較的是兩個字符串中對應位置的每個字符的字符編碼值。經(jīng)過這么一番比較后怔蚌,再返回一個布爾值巩步。由于大寫字母的字符編碼全部小于小寫字母的字符編碼,因此我們就會看到如下所示的奇怪現(xiàn)象:
var result = "Brick" < "alpahabet"; //true
要真正按照字母表順序比較字符串桦踊,就必須把兩個操作數(shù)轉換為相同的大小寫形式渗钉,然后在執(zhí)行比較,如下所示:
var result = "Brick.toLowerCase()" < "alphabet".toLowerCase(); //false
var result = "23" < "3"; //true
var result = "23" < 3; //false
var result = "a" < 3; //false,因為“a”被轉換成了NaN
var result1 = NaN < 3; //false
var result2 = NaN >= 3; //false
按照常理,如果一個值不小于另一個值鳄橘,則一定是大于或等于那個值声离。然而,在與NaN
進行比較時瘫怜,這兩個比較操作的結果都返回了fasle
术徊。
3.5.7 相等操作符
在比較字符串、數(shù)值和布爾值的的相等性時鲸湃,問題還比較簡單赠涮。但在涉及到對象的比較時,問題就變得復雜了暗挑。最后笋除,ECMAScript的解決方案就是提供兩組操作符:相等和不相等——先轉換在比較,全等和不全等——僅比較而不轉換炸裆。
1.相等和不相等
會先轉換操作數(shù)垃它,然后再比較它們的相等性。在轉換不同的數(shù)據(jù)類型時烹看,相等和不相等操作符遵循下列基本規(guī)則:
- 如果有一個操作數(shù)是布爾值国拇,則在比較相等性之前先將其轉換為數(shù)值——
false
轉換為0,而true
轉換為1惯殊; - 如果一個操作數(shù)是字符串酱吝,另一個操作數(shù)是數(shù)值,在比較相等性之前先將字符串轉換為數(shù)值土思;
- 如果一個操作數(shù)是對象务热,另一個操作數(shù)不是,則調用對象的
valueOf()
方法己儒,用得到的基本類型值按照前面的規(guī)則進行比較陕习;
這兩個操作符在進行比較時則要遵循下列規(guī)則。
-
null
和undefined
是相等的址愿。 - 要比較相等性之前该镣,不能將
null
和undefined
轉換成其他任何值。 - 如果有一個操作數(shù)是
NaN
响谓,則相等操作符返回false
损合,而不相等操作符返回true
。重要提示:即使兩個操作數(shù)都是NaN
娘纷,相等操作符也返回false
嫁审;按照規(guī)則,NaN
不等于NaN
赖晶。 - 如果兩個操作數(shù)都是對象律适,則比較它們是不是同一個對象辐烂。如果兩個操作數(shù)都指向同一個對象,則相等操作符返回
true
捂贿;否則纠修,返回false
。
下表列出了一些特殊情況及比較結果:
表達式 | 值 |
---|---|
null == undefined | true |
"NaN" == NaN | false |
5 == NaN | false |
NaN == NaN | false |
NaN != NaN | true |
false == 0 | true |
true == 1 | true |
true == 2 | false |
undefined == 0 | false |
null == 0 | false |
"5" == 5 | true |
2.全等和不全等
只在兩個操作數(shù)未經(jīng)轉換就相等的情況下返回true
厂僧。
var result1 = ("55" == 55); //true扣草,因為轉換后相等
var result2 = ("55" === 55); //false颜屠,因為不同的數(shù)據(jù)類型不相等
var result1 = ("55" != 55); //false辰妙,因為轉換后相等
var result2 = ("55" !== 55); //true,因為不同的數(shù)據(jù)類型不相等
3.5.8 條件操作符
variable = boolean_expression ? true_value : false_value;
var max = (num1 > num2) ? num1: num2;
3.5.9 賦值操作符
var num = 10;
var num = 10;
num += 10;
每個主要算術操作符(以及個別的其他操作符)都有對應的復合賦值操作符甫窟。這些操作符如下所示:
- 乘/賦值 (*=)密浑;
- 除/賦值 (/=);
- 模/賦值 (%=)粗井;
- 加/賦值 (+=)尔破;
- 減/賦值 (-=);
- 左移/賦值 (<<=)背传;
- 有符號右移/賦值 (>>=)呆瞻;
- 無符號右移/賦值 (>>>=)台夺。
3.5.10 逗號操作符
使用逗號操作符可以在一條語句中執(zhí)行多個操作径玖。
var num1 =1, num2 = 2, num3 = 3;
逗號操作符還可以用于賦值。在用于賦值時颤介,逗號操作符總會返回表達式中的最后一項梳星。
var num = (5, 1, 4, 8, 0); //num的值為0
由于0是表達式中的最后一項,因此num
的值就是0滚朵。
3.6 語句
從本質上看冤灾,語句定義了ECMAScript中的主要語法,語句通常使用一或多個關鍵字來完成給定任務辕近。
3.6.1 if 語句
if (condition) statement1 else statement2
if (i > 25)
alert("Greater than 25."); //單行語句
esle {
alert("Less than or equal to 25."); //代碼塊中的語句
}
不過韵吨,業(yè)界普遍推崇的最佳實踐是始終使用代碼塊,即使要執(zhí)行的只有一行代碼移宅。
另外归粉,也可以把整個if
語句寫在一行代碼中:
if (condition1) statement1 else if (condition2) statement2 else statement3
但我們推薦的做法則是像下面這樣:
if (i > 25) {
alert("Greater than 25.");
} else if (i < 0) {
alert("Less than 0.");
} else {
alert("Between 0 and 25, inclusive.");
}
3.6.2 do-while 語句
do-while
語句是一種后測試循環(huán)語句,即只有在循環(huán)體中的代碼執(zhí)行之后漏峰,才會測試出口條件糠悼。
do {
statement
} while (expression);
var i = 0;
do {
i += 2;
} while (i < 10);
alert(i);
3.6.3 while 語句
while
語句屬于前測試循環(huán)語句,也就是說浅乔,在循環(huán)體內的代碼被執(zhí)行之前倔喂,就會對出口條件求值。
while(expression) statement
var i = 0;
while (i < 10) {
i +=2;
}
3.6.4 for語句
for
語句也是一種前測試循環(huán)語句,但它具有在執(zhí)行循環(huán)之前初始化變量和定義循環(huán)后要執(zhí)行的代碼的能力席噩。
for (initialization; expression; post-loop-expression) statement
var count = 10;
for (var i = 0; i < count; i++) {
alert(i);
}
這個for
循環(huán)語句與下面的while
語句的功能相同:
var count = 10;
var i = 0;
while (i < count) {
alert(i);
i++;
}
變量初始化可以在外部執(zhí)行班缰,由于ECMAScript中不存在塊級作用域,因此在循環(huán)內部定義的變量也可以在外部訪問到班挖。
此外鲁捏,for
語句中的初始化表達式、控制表達式和循環(huán)后表達式都是可選的萧芙。將這兩個表達式全部省略给梅,就會創(chuàng)建一個無限循環(huán)。
for (; ;) { //無限循環(huán)
doSomething();
}
而只給出控制表達式實際上就把for
循環(huán)轉換成了while
循環(huán)双揪。
var count = 10;
var i = 0;
for (; i < count; ) {
alert(i);
i++;
}
3.6.5 for-in 語句
for-in
語句是一種精準的迭代語句动羽,可以用來枚舉對象的屬性。
for (property in expression) statement
for (var propName in window) {
document.write(propName);
}
ECMAScript對象的屬性沒有順序渔期。因此运吓,通過for-in
循環(huán)輸出的屬性名的順序是不可預測的。
但是疯趟,如果表示要迭代的對象的變量值為null
或undefined
拘哨,for-in
語句會拋出錯誤。ECMAScript5更正了這一行為信峻;對這種情況不再拋出錯誤倦青,而只是不執(zhí)行循環(huán)體。建議在使用for-in
循環(huán)之前盹舞,先檢測確認該對象的值不是null
或undefined
产镐。
3.6.6 label語句
使用label
語句可以在代碼中添加標簽,以便將來使用踢步。
label: statement
start: for(var i=0; i < count; i++) {
alert(i);
}
這個例子中定義的start
標簽可以在將來由break
或continue
語句引用癣亚。加標簽的語句一般都要與for
語句等循環(huán)語句配合使用。
3.6.7 break和continue語句
break
和continue
語句用于在循環(huán)中精確控制代碼的執(zhí)行获印。其中述雾,break
語句會立即退出循環(huán),強制繼續(xù)執(zhí)行循環(huán)后面的語句兼丰。而continue
語句雖然也是立即退出循環(huán)玻孟,但退出循環(huán)后會從循環(huán)的頂部繼續(xù)執(zhí)行。
var num = 0;
for (var i = 1; i < 10; i++) {
if(i % 5 == 0) {
break;
}
num++;
}
alert(num); //4
var num = 0;
for (var i = 1; i < 10; i++) {
if(i % 5 == 0) {
continue;
}
num++;
}
alert(num); //8
break
和continue
語句都可以與label
語句聯(lián)合使用地粪,從而返回代碼中特定的位置取募。
var num = 0;
outermost:
for (var i = 0; i < 10; i++) {
for(var j = 0; j < 10; j++) {
if(i == 5 && j == 5) {
break outermost;
}
num++;
}
}
alert(num); //55
添加這個標簽的結果將導致break
語句不僅會退出內部的for
語句,而且也會退出外部的for
語句蟆技。
3.6.8 with語句
with
語句的作用是將代碼的作用域設置到一個特定的對象中玩敏。
with (expression) statement;
定義with
語句的目的主要是為了簡化多次編寫同一個對象的工作斗忌。
var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href;
with(location) {
var qs = search.substring(1);
var hostName = host.name;
var url = href;
}
嚴格模式下不允許使用with
語句,否則將視為語法錯誤旺聚。
不建議使用with
語句织阳。
3.6.9 switch語句
ECMAScript中switch
語句的語法與其他基于C的語言非常接近。
switch (expression) {
case value: statement
break;
case value: statement
break;
case value: statement
break;
case value: statement
break;
default: statement
}
假如確實需要混合幾種情形砰粹,不要忘了在代碼中添加注釋唧躲,說明你是有意省略了break
關鍵字。
switch(i) {
case 25:
/*合并兩種情形*/
case 35:
alert("25 or 35");
break;
case 45:
alert("45");
break;
default:
alert("other");
}
可以在switch
語句中使用任何數(shù)據(jù)類型碱璃,無論是字符串弄痹,還是對象都沒有問題。嵌器。每個case
的值不一定是常量肛真,可以是變量,甚至是表達式爽航。
switch
語句在比較值時使用的是全等操作符蚓让,因此不會發(fā)生類型轉換。
3.7 函數(shù)
ECMAScript中的函數(shù)使用function
關鍵字來聲明讥珍,后跟一組參數(shù)以及函數(shù)體历极。
function functionName(arg0, arg1, ..., argN) {
statements
}
function sayHi(name, message) {
alert("hello " + name + "," + message);
}
實際上,任何函數(shù)在任何時候都可以通過return
語句后跟要返回的值來實現(xiàn)返回值衷佃。
function sum(num1, num2) {
return num1 + num2;
}
return
語句也可以不帶有任何返回值趟卸。在這種情況下,函數(shù)在停止執(zhí)行后將返回undefined
值纲酗。這種用法一般用在需要提前停止函數(shù)執(zhí)行而又不需要返回值的情況下衰腌。
推薦的做法是要么讓函數(shù)始終都返回一個值新蟆,要么永遠都不要返回值觅赊。
嚴格模式對函數(shù)有一些限制:
- 不能把函數(shù)命名為
eval
或arguments
; - 不能把參數(shù)命名為
eval
或arguments
; - 不能出現(xiàn)兩個命名參數(shù)同名的情況琼稻。
如果發(fā)生以上情況吮螺,就會導致語法錯誤,代碼無法執(zhí)行帕翻。
3.7.1 理解函數(shù)
在函數(shù)體內可以通過arguments
對象來訪問這個參數(shù)數(shù)組鸠补,從而獲取傳遞給函數(shù)的每一個參數(shù)。
arguments
對象只是與數(shù)組類似嘀掸,因為可以使用方括號語法訪問它的每一個元素紫岩,使用length
屬性來確定傳遞進來多少個參數(shù)。
function sayHi() {
alert("hello " + arguments[0] + "," + arguments[1]);
}
這個重寫后的函數(shù)中不包含命名的參數(shù)睬塌。這個事實說明:命名的參數(shù)只提供便利泉蝌,但不是必需的歇万。
通過訪問arguments
對象的length
屬性可以獲知有多少個參數(shù)傳遞給了函數(shù)。
function howManyArgs() {
alert(arguments.length);
}
howManyArgs("string", 45); //2
howManyArgs(); //0
howManyArgs(12); //1
開發(fā)人員可以利用這一點讓函數(shù)能夠接收任意個參數(shù)并分別實現(xiàn)適當?shù)墓δ堋?/p>
function doAdd() {
if(arguments.length == 1) {
alert(arguments[0] + 10);
} else if (arguments.length == 2) {
alert(arguments[0] + arguments[1]);
}
}
doAdd(10); //20
doAdd(30, 20); //50
另一個與參數(shù)相關的重要方面勋陪,就是arguments
對象可以與命名參數(shù)一起使用贪磺。
function doAdd(num1, num2) {
if(arguments.length ==1) {
alert(num1 + 10);
} else if (arguments.length == 2) {
alert(arguments[0] + num2);
}
}
關于arguments
的行為,還有一點比較有意思诅愚。那就是它的值永遠與對應命名參數(shù)的值保持同步寒锚。
function doAdd(num1, num2) {
arguments[1] = 10;
alert(arguments[0] + num2);
}
每次執(zhí)行這個函數(shù)都會重寫第二個參數(shù),將第二個參數(shù)的值修改為10.因為arguments
對象中的值會自動反映到對應的命名參數(shù)违孝。它們的內存空間是獨立的刹前,但它們的值會同步。但這種影響是單向的:修改命名參數(shù)不會改變arguments
中對應的值雌桑。如果只傳入了一個參數(shù)腮郊,那么為arguments[1]
設置的值不會反應到命名參數(shù)中。這是因為arguments
對象的長度是由傳入的參數(shù)個數(shù)決定的筹燕,不是由定義函數(shù)時的命名參數(shù)的個數(shù)決定的轧飞。
關于參數(shù)還要記住最后一點:沒有傳遞值的命名參數(shù)將自動被賦予undefined
值。
嚴格模式中撒踪,像前面例子中那樣的賦值會變得無效过咬,即使把arguments[1]
設置為10,num2
的值仍然還是undefined
制妄。其次掸绞,重寫arguments
的值會導致語法錯誤。
ECMAScript中的所有參數(shù)傳遞的都是值耕捞,不可能通過引用傳遞參數(shù)衔掸。
3.7.2 沒有重載
ECMAScript函數(shù)不能像傳統(tǒng)意義上那樣實現(xiàn)重載。
如果在ECMAScript中定義了兩個名字相同的函數(shù)俺抽,則該名字只屬于后定義的函數(shù)敞映。
function addSomeNumber(num) {
return num + 100;
}
function addSomeNumber(num) {
return num + 200;
}
var result = addSomeNumber(100); //300
3.8 小結
以下簡要總結了ECMAScript中基本的要素。
- ECMAScript中的基本數(shù)據(jù)類型包括
Undefined
磷斧、Null
振愿、Booelan
、Number
和String
弛饭。 - 與其他語言不同冕末,ECMAScript沒有為整數(shù)和浮點數(shù)值分別定義不同的數(shù)據(jù)類型,
Number
類型可用于表示所有數(shù)值侣颂。 -
Object
類型档桃,該類型是這門語言中所有對象的基礎類型。 - 嚴格模式為這門語言中容易出錯的地方施加了限制憔晒。
- ECMAScript提供了很多與C及其其他類C語言中相同的基本操作符藻肄,包括算數(shù)操作符销凑、布爾操作符、關系操作符仅炊、相等操作符及賦值操作符等斗幼。
- 從其他語言借鑒了很多流控制語句,例如
if
語句抚垄、for
語句和switch
語句等蜕窿。
ECMAScript中的函數(shù)與其他語言中的函數(shù)有諸多不同之處。
- 無須指定函數(shù)的返回值呆馁。
- 實際上桐经,未指定返回值的函數(shù)返回的是一個特殊的
undefined
值。 - ECMAScript中也沒有函數(shù)簽名的概念浙滤,因為其函數(shù)參數(shù)是以一個包含零或多個值的數(shù)組的形式傳遞的阴挣。
- 可以向ECMAScript函數(shù)傳遞任意數(shù)量的參數(shù),并且可以通過
arguments
對象來訪問這些參數(shù)纺腊。 - 由于不存在函數(shù)簽名的特性畔咧,ECMAScript函數(shù)不能重載。