第四章:表達(dá)式和運(yùn)算符
2017.02.21-2017.02.22
表達(dá)式和運(yùn)算符
表達(dá)式(expression):JavaScript解釋器會(huì)將其計(jì)算出一個(gè)結(jié)果。
運(yùn)算符(operator):將簡(jiǎn)單表達(dá)式組合成復(fù)雜表達(dá)式最常用的方法就是運(yùn)算符占锯。
原始表達(dá)式
原始表達(dá)式子(primary expression):表達(dá)式的最小單位卓嫂,它們不再包含其他表達(dá)式涡拘。JavaScript中的原始表達(dá)式包含常量或直接量换衬,關(guān)鍵字和變量炸卑。
直接量
1.23 //數(shù)字直接量
"hello" //字符串直接量
/pattern/ //正則表達(dá)式直接量
保留字
true
false
null
this
變量
i
sum
undefined // undefined是全局變量,與null不同录豺,他不是關(guān)鍵字
對(duì)象和數(shù)組的初始化表達(dá)式
對(duì)象和數(shù)組初始化表達(dá)式實(shí)際上是一個(gè)新創(chuàng)建的對(duì)象和數(shù)組朦肘。這些初始化表達(dá)式有時(shí)稱作“對(duì)象直接量”和“數(shù)組直接量”。它們不是原始表達(dá)式双饥,它們所包含的成員或者元素都是子表達(dá)式媒抠。
數(shù)組初始化表達(dá)式
[] //空數(shù)組
[1+2,3+4] //有兩個(gè)元素的數(shù)組
var matrix=[[1,2,3],[4,5,6],[7,8,9]];
JavaScript對(duì)數(shù)組初始化表達(dá)式進(jìn)行求值的時(shí)候,數(shù)組初始化表達(dá)式中的元素表達(dá)式也都會(huì)各自計(jì)算一次咏花。
var x=1;
var a=[[x+++1,2],[x+++1,2],[x+++1,2]] //結(jié)果[ [ 2, 2 ], [ 3, 2 ], [ 4, 2 ] ]
數(shù)組直接兩種列表逗號(hào)之間的元素可以省略趴生,省略的空位會(huì)填充值undefined。
var arr=[1,,,,5];//arr打印結(jié)果:[ 1, , , , 5 ]
arr[0]; //1
arr[1]; //undefined
arr[4]; //5
數(shù)組直接量的元素列表結(jié)尾可以留下單個(gè)逗號(hào)昏翰,這時(shí)并不會(huì)創(chuàng)建一個(gè)新的值為undefined的元素苍匆。
var arr=[1,,,,5,]; //arr打印結(jié)果[ 1, , , , 5 ]
對(duì)象初始化表達(dá)式
var p={x:2.3,y:-1.2}; //擁有兩個(gè)屬性成員的對(duì)象
var q={}; //空對(duì)象
q.x=2.3;q.y=-1.2; //此時(shí)q是{x:2.3;y:-1.2}
var rectangle={upperLeft:{x:2,y:2},lowerRight:{x:4,y:4}};
var side=1;
var square={upperLeft:{x:p.x,y:p.y},lowerRight:{x:p.x+side,y:p.y+side}};
var p={"x":2.3,"y":-1.2}; //打印結(jié)果 { x: 2.3, y: -1.2 },參考json
p.x //2.3
p."x" //SyntaxError: Unexpected string
p[x] //undefined,此處x會(huì)被當(dāng)做變量棚菊。倘若var x="x"浸踩,那么p[x] 也是2.3
p["x"] //2.3
函數(shù)定義表達(dá)式
函數(shù)定義表達(dá)式定義一個(gè)新的JavaScript函數(shù)。表達(dá)式的值是新定義的函數(shù)统求。函數(shù)定義表達(dá)是可稱為“函數(shù)直接量”检碗。
一個(gè)典型的函數(shù)定義表達(dá)式包含關(guān)鍵字function,跟隨其后的是一對(duì)圓括號(hào)码邻,括號(hào)內(nèi)是一個(gè)以逗號(hào)分割的列表折剃,列表含有0個(gè)或多個(gè)標(biāo)識(shí)符(參數(shù)名),然后在跟隨一個(gè)由花括號(hào)包裹的代碼段(函數(shù)體)像屋。
var square=function(x){return x*x};
函數(shù)定義表達(dá)式同樣可以包含函數(shù)的名字怕犁。函數(shù)可以通過(guò)函數(shù)語(yǔ)句來(lái)定義,而不是函數(shù)表達(dá)式己莺。
屬性訪問(wèn)表達(dá)式
屬性訪問(wèn)表達(dá)式運(yùn)算得到一個(gè)對(duì)象屬性或一個(gè)數(shù)組元素的值因苹。
【語(yǔ)法】
expression.identifier //用于對(duì)象
expression[expression] //用于對(duì)象、數(shù)組
【示例】
var o={x:1,y:{z:3}};
var a=[o,4,[5,6]];
o.x;//1
o.y.z;//3
o["x"];//1
a[0];//{ x: 1, y: { z: 3 } }
a[1];//4
a[2][1];//6
a[2]["1"];//6 a["2"][1];//6 a["2"]["1"];//6
a[0].x;//1
a[0]["x"];//1
for(var each in this){console.log(each+":"+this[each])} //打印對(duì)象中所有屬性以及其值
在"."和"["之前的表達(dá)式總是會(huì)首先計(jì)算篇恒。如果計(jì)算結(jié)果是null或undefined扶檐,表達(dá)式會(huì)拋出類型錯(cuò)誤異常。(因?yàn)檫@兩個(gè)值不包含任意屬性)胁艰。如果運(yùn)算結(jié)果不是對(duì)象(或數(shù)組)款筑,JavaScript會(huì)將其轉(zhuǎn)換成對(duì)象。如果對(duì)象表達(dá)式后緊隨句點(diǎn)和標(biāo)識(shí)符腾么,則會(huì)差債有這個(gè)標(biāo)識(shí)符所指定的屬性的值奈梳,并將其作為整個(gè)表達(dá)式的值返回。如果對(duì)象表達(dá)式后緊隨一堆方括號(hào)解虱,則會(huì)計(jì)算方括號(hào)內(nèi)的表達(dá)式的值并將它轉(zhuǎn)換為字符串攘须。如果屬性不存在,返回undefined殴泰。
identitier寫法簡(jiǎn)單于宙,但要注意浮驳,此方式只適用于要訪問(wèn)的屬性名稱合法,并且需要知道要訪問(wèn)的屬性的名字捞魁。如果屬性名稱是一個(gè)保留字或者包含空格和標(biāo)點(diǎn)符號(hào)或是一個(gè)數(shù)字至会,則必須使用方括號(hào)。當(dāng)屬姓名是通過(guò)運(yùn)算得出來(lái)的值而不是固定的值得時(shí)候谱俭,這是必須使用方括號(hào)奉件。
調(diào)用表達(dá)式
調(diào)用表達(dá)式(invocation expression):是一種調(diào)用(或者執(zhí)行)函數(shù)或方法的語(yǔ)法表示。以一個(gè)函數(shù)表達(dá)式開(kāi)始昆著,這個(gè)函數(shù)表達(dá)式指代要調(diào)用的函數(shù)县貌,函數(shù)表達(dá)式后緊隨一對(duì)包含一逗號(hào)隔開(kāi)的參數(shù)列表的圓括號(hào)。
f(0)
Math.max(x,y,z)
a.sort() //關(guān)于這個(gè)函數(shù)凑懂,戳下面鏈接
當(dāng)調(diào)用表達(dá)式進(jìn)行求職的時(shí)候煤痕,首先計(jì)算函數(shù)表達(dá)式,然后計(jì)算參數(shù)表達(dá)式征候,得到一組參數(shù)值杭攻。如果函數(shù)表達(dá)式的值不是一個(gè)可調(diào)用的對(duì)象,則拋出一個(gè)類型錯(cuò)誤異常疤坝。然后兆解,實(shí)參的值被依次賦給形參,接下來(lái)執(zhí)行函數(shù)體跑揉。如果函數(shù)使用return語(yǔ)句給出一個(gè)返回值锅睛,那么這個(gè)返回值就是整個(gè)調(diào)用表達(dá)式的值,否則历谍,調(diào)用表達(dá)式的值就是undefined现拒。
如果調(diào)用表達(dá)式是一個(gè)屬性訪問(wèn)表達(dá)式,則此調(diào)用稱作“方法調(diào)用”望侈。
對(duì)象創(chuàng)建表達(dá)式
對(duì)象創(chuàng)建表達(dá)是(object creation expression):創(chuàng)建一個(gè)對(duì)象并調(diào)用一個(gè)函數(shù)(構(gòu)造函數(shù))初始化新對(duì)象的屬性印蔬。
new Object()
new Point(2,3)
如果一個(gè)對(duì)象創(chuàng)建表達(dá)式不需要傳入任何參數(shù)給構(gòu)造函數(shù)的話,那么這對(duì)空?qǐng)A括號(hào)是可以省略掉的脱衙。
new Object
new Date
當(dāng)計(jì)算一個(gè)對(duì)象創(chuàng)建表達(dá)式的值時(shí)侥猬,和對(duì)象初始化表達(dá)式通過(guò){}創(chuàng)建對(duì)象的做法一樣,JavaScript首先創(chuàng)建一個(gè)新的空對(duì)象捐韩,然后JavaScript通過(guò)傳入指定的參數(shù)并將這個(gè)新對(duì)象當(dāng)做this的值來(lái)調(diào)用一個(gè)指定的函數(shù)退唠。這個(gè)函數(shù)可以使用this來(lái)初始化這個(gè)新創(chuàng)建對(duì)象的屬性。那些被當(dāng)做構(gòu)造函數(shù)的函數(shù)不會(huì)反悔一個(gè)值荤胁,并且這個(gè)新創(chuàng)建并被初始化后的對(duì)象就是整個(gè)對(duì)象創(chuàng)建表達(dá)式的值瞧预。如果一個(gè)構(gòu)造函數(shù)確實(shí)返回了一個(gè)對(duì)象值,那么這個(gè)對(duì)象就作為整個(gè)對(duì)象創(chuàng)建表達(dá)式的值,而新創(chuàng)建的對(duì)象就廢棄了垢油。
運(yùn)算符概述
JavaScript中的運(yùn)算符用于算術(shù)表達(dá)式盆驹、比較表達(dá)式、邏輯表達(dá)式秸苗、復(fù)制表達(dá)式等召娜。
包括關(guān)鍵字運(yùn)算符(delete运褪,instanceof)和標(biāo)點(diǎn)符號(hào)(+惊楼,=)所表示的運(yùn)算符摘符。
操作數(shù)的個(gè)數(shù)
- 一元運(yùn)算符 unary operator
- 二元運(yùn)算符 binary operator
- 三元運(yùn)算符 ternary operator
操作數(shù)類型和結(jié)果類型
一些運(yùn)算符可以作用于任何數(shù)據(jù)類型尉辑,但仍希望它們的操作數(shù)是指定類型的數(shù)據(jù)铡俐,并大多數(shù)運(yùn)算符返回一個(gè)特定類型的值腰奋。
左值
左值是指:表達(dá)式只能出現(xiàn)在賦值運(yùn)算符的左側(cè)蚀之。在JavaScript中袱院,變量嘁字、對(duì)象屬性和數(shù)組元素均是左值蒿往。
ECMAScript規(guī)范允許內(nèi)置函數(shù)返回一個(gè)左值劣欢,但自定義的函數(shù)則不能返回左值棕诵。(?)
運(yùn)算優(yōu)先級(jí)
屬性訪問(wèn)表達(dá)式和調(diào)用表達(dá)式的優(yōu)先級(jí)比表中運(yùn)算符都要高。
運(yùn)算順序
JavaScript總是嚴(yán)格按照從左至右的順序來(lái)計(jì)算表達(dá)式凿将。
算術(shù)表達(dá)式
* / % -
無(wú)法轉(zhuǎn)換為數(shù)字的操作數(shù)都轉(zhuǎn)換為NaN校套,結(jié)果也是NaN。
對(duì)于除法/
牧抵,JavaScript中所有數(shù)字都是浮點(diǎn)型的笛匙,除法運(yùn)算的結(jié)果也是浮點(diǎn)型。
5/2 //2.5
0/0 //NaN
1/0 //Infinity
-1/0 //-Infinity
對(duì)于取模%
犀变,結(jié)果和第一個(gè)操作數(shù)的符號(hào)保持一致妹孙。操作數(shù)通常是整數(shù),但也適用于浮點(diǎn)數(shù)获枝。
5%2 //1
-5%2 //-1
6.5%2.1 //0.19999999999999973
+
運(yùn)算符
1+2 //3
"hello"+" "+"there" //"hello there"
"1"+"2" //"12"
- 如果其中一個(gè)操作數(shù)是對(duì)象蠢正,則對(duì)象會(huì)遵循對(duì)象到原始值的轉(zhuǎn)換規(guī)則轉(zhuǎn)換為原始類值。日期獨(dú)享通過(guò)toString()方法轉(zhuǎn)換省店,群毆他對(duì)象通過(guò)valueOf()轉(zhuǎn)換(如果valueOf()返回原始值的話)嚣崭。由于多數(shù)都不具備valueOf()方法,因此會(huì)通過(guò)toString()轉(zhuǎn)換萨西。
- 在進(jìn)行了對(duì)象到運(yùn)勢(shì)值的轉(zhuǎn)換之后有鹿,如果一個(gè)操作數(shù)是字符串,另一個(gè)操作數(shù)也會(huì)轉(zhuǎn)換為字符串谎脯,然后進(jìn)行字符串連接葱跋。
- 否則,兩個(gè)操作數(shù)都轉(zhuǎn)換為數(shù)字(或NaN),然后進(jìn)行加法運(yùn)算
【示例】
1+2 //3;加法
"1"+"2" // "12";字符串連接
"1"+2 //"12";數(shù)字轉(zhuǎn)換為字符串后進(jìn)行字符串連接
1+{} //"1[object Object]" ;對(duì)象轉(zhuǎn)換為字符串后進(jìn)行字符串連接
true+true //2;布爾值轉(zhuǎn)換為數(shù)字后加法
2+null; //2;null轉(zhuǎn)換為0后加法
2+undefined //NaN;undefined轉(zhuǎn)換為NaN后加法
需要注意的是娱俺,加號(hào)運(yùn)算符和字符串和數(shù)字一起使用時(shí)稍味,需要考慮加法的結(jié)核性對(duì)運(yùn)算順序的影響。
1+2+"hello" // "3hello"
1+(2+"hello") //"12hello"
一元算術(shù)運(yùn)算符
一元運(yùn)算符作用域一個(gè)單獨(dú)的操作數(shù)荠卷,產(chǎn)生一個(gè)新值模庐。一元運(yùn)算符優(yōu)先級(jí)很高,右結(jié)合(right-associative)油宜。
+
把操作數(shù)轉(zhuǎn)換為數(shù)字(或NaN)掂碱,并返回轉(zhuǎn)換后的數(shù)字。如果操作數(shù)本身就是數(shù)字慎冤,則直接返回?cái)?shù)字疼燥。
-
把操作數(shù)轉(zhuǎn)換為數(shù)字,然后改變運(yùn)算結(jié)果的符號(hào)蚁堤。
++
加一醉者,操作數(shù)是一個(gè)左值。將操作數(shù)轉(zhuǎn)換為數(shù)字披诗,然后給數(shù)字加一撬即,并將加一后的數(shù)值重新賦值給操作數(shù)(變量、數(shù)組元素或者對(duì)象屬性)呈队。
前增量:運(yùn)算符在操作數(shù)之前的剥槐。
后增量:運(yùn)算符在操作數(shù)之后的。不允許后增量運(yùn)算符和操作數(shù)之間插入換行符掂咒。
var i=1;j=++1; //i=2,j=2
var i=1;j=i++; //i=2,j=1
x++
不等于x=x+1
才沧,++
從不進(jìn)行字符串連接操作。
var x='1';
x++; //2
x=x+1; // 11
--
減一绍刮,操作數(shù)是一個(gè)左值温圆。將操作數(shù)轉(zhuǎn)換為數(shù)字,然后減一孩革,并將減一后的數(shù)值重新賦值給操作數(shù)(變量岁歉、數(shù)組元素或者對(duì)象屬性)。
運(yùn)算符在操作數(shù)之前膝蜈,操作數(shù)減一并返回減一后的值锅移。
運(yùn)算符在操作數(shù)之后,操作數(shù)減一并返回減一前的值饱搏。不允許運(yùn)算符和操作數(shù)之間有換行符非剃。
位運(yùn)算符
位運(yùn)算符要求其操作數(shù)是整數(shù),這些證書(shū)表示為32位整型而不是64位浮點(diǎn)型推沸。必要時(shí)备绽,位運(yùn)算符首先將操作符轉(zhuǎn)換為數(shù)字券坞,并將數(shù)字強(qiáng)制表示為32位整型,這會(huì)忽略原格式中的小數(shù)部分和任何超過(guò)32位的二進(jìn)制位肺素。移位運(yùn)算符要求又操作數(shù)在0-31之間恨锚。在將其操作數(shù)轉(zhuǎn)換為無(wú)符號(hào)32位整數(shù)后,它們將舍棄第5位之后的二進(jìn)制位倍靡,以便生成一個(gè)位數(shù)正確的數(shù)字猴伶。位運(yùn)算符將NaN、Infinity塌西、-Infinity轉(zhuǎn)換為0他挎。
-
&
按位與 -
|
按位或 -
^
按位異或 -
~
按位非,相當(dāng)于改變符號(hào)并減一雨让。 ~0x0f=0xfffffff0 即15按位非后是-16 -
<<
左移雇盖,新的位用0補(bǔ)充忿等,并舍棄高位栖忠。左移n位相當(dāng)于乘以2^n -
>>
帶符號(hào)右移,如果第一個(gè)操作數(shù)是正數(shù)贸街,用0填補(bǔ)最高位庵寞;如果第一個(gè)操作室是負(fù)數(shù),用1填補(bǔ)最高位薛匪。將一個(gè)值右移n位捐川,相當(dāng)于除以2^n(忽略余數(shù))。7>>1=3;-7>>1=-4 -
>>>
無(wú)符號(hào)右移逸尖,最高位總是補(bǔ)0古沥。 -1>>4=1-;-1>>>4=0x0FFFFFFF
關(guān)于無(wú)符號(hào)數(shù),有符號(hào)數(shù)娇跟。
> 0xFFFFFFFF
4294967295
> 0xFFFFFFFF>>>0
4294967295
> 0xFFFFFFFF<<0
-1
> 0xFFFFFFFF>>0
-1
關(guān)系表達(dá)式
相等岩齿,不相等
===
嚴(yán)格相等運(yùn)算符(恒等運(yùn)算符),用來(lái)檢測(cè)兩個(gè)操作數(shù)是否嚴(yán)格相等苞俘。對(duì)應(yīng)的有!==
==
相等運(yùn)算符盹沈,用來(lái)檢測(cè)兩個(gè)操作數(shù)是否相等,可以允許進(jìn)行類型轉(zhuǎn)換吃谣。對(duì)應(yīng)的有!=
===
- 如果兩個(gè)值類型不相同乞封,則它們不相等。
- 如果兩個(gè)值都是null或者都是undefined岗憋,則它們相等肃晚。
null===null(true)undefined===undefined(true)
。(注意:中文版仔戈,淘寶團(tuán)隊(duì)翻譯的有錯(cuò)誤关串。翻譯為不想等了惋鸥。)null,undefined,Infinity,-Infinity只要兩者本身值或者計(jì)算后的值相等,那么他們就恒等悍缠。 - 如果兩個(gè)值都是布爾值true或者都是布爾值false卦绣,則它們相等
- 如果其中一個(gè)值是NaN,或者兩個(gè)值都是NaN飞蚓,則它們不相等滤港。NaN和其他任何值都不想等,包括他自己趴拧。通過(guò)
x!=x
判斷x是否位NaN溅漾,只有在x為NaN時(shí),這個(gè)表達(dá)式的值才是true著榴。 - 如果兩個(gè)值為數(shù)字且數(shù)值相等添履,則它們相等。如果一個(gè)值為0脑又,另一個(gè)值為-0暮胧,則它們同樣相等。
- 如果兩個(gè)值為字符串问麸,且所含的對(duì)應(yīng)位上的16位數(shù)完全相等往衷,則它們相等。如果長(zhǎng)度或內(nèi)容不同严卖,則它們不等席舍。兩個(gè)字符串可能含義完全一樣且所顯示出的字符也一樣,但是具有不同編碼的16位值哮笆。JavaScript不對(duì)Unicode進(jìn)行標(biāo)準(zhǔn)化的轉(zhuǎn)換来颤,因此像這樣的字符串通過(guò)
===
==
比較的結(jié)果不相等。String.localeCompare()提供了另外一種比較字符串的方法稠肘。 - 如果兩個(gè)引用值指向同一個(gè)對(duì)象福铅、數(shù)組或函數(shù),則它們相等启具。如果指向不同對(duì)象本讥,則它們不相等,盡管兩個(gè)對(duì)象具有完全一樣的屬性鲁冯。
==
- 如果兩個(gè)操作數(shù)的類型相同拷沸,則和上文所述的比較規(guī)則一樣。如果嚴(yán)格相等薯演,那么比較結(jié)果相等撞芍,如果不嚴(yán)格相等,則比較結(jié)果不相等跨扮。
- 如果兩個(gè)操作數(shù)類型不同:
- 一個(gè)null序无,另一個(gè)undefined验毡,則它們相等。
null==undefined
- 一個(gè)值是數(shù)字帝嗡,另一個(gè)是字符串晶通,現(xiàn)將字符串轉(zhuǎn)換為數(shù)字,然后比較
- 如果一個(gè)值為true哟玷,則將其轉(zhuǎn)換為1再比較狮辽。如果一個(gè)值位false,則將其轉(zhuǎn)換為0再比較
true==1:true;true==2:false;true=="1":true
- 如果一個(gè)值是對(duì)象巢寡,另一個(gè)值是數(shù)字或字符串喉脖,則使用轉(zhuǎn)換規(guī)則將對(duì)象轉(zhuǎn)換為原始值,然后比較抑月。
- 其他的不同類型之間的比較均不相等树叽。
- 一個(gè)null序无,另一個(gè)undefined验毡,則它們相等。
比較運(yùn)算符
-
<
小于 -
>
大于 -
<=
小于等于 -
>=
大于等于
只有數(shù)字和字符串才能執(zhí)行比較操作,非數(shù)字和字符串都要進(jìn)行類型轉(zhuǎn)換谦絮。規(guī)則如下:
- 如果操作數(shù)是對(duì)象题诵,轉(zhuǎn)換為原始值:如果valueOf()返回原始值,那么直接使用這個(gè)原始值挨稿。否則仇轻,使用toString()的轉(zhuǎn)換結(jié)果進(jìn)行比較。
- 在對(duì)象轉(zhuǎn)換為原始值之后奶甘,如果兩個(gè)操作數(shù)都是字符串,將依照字母表的順序?qū)蓚€(gè)字符串比較祭椰。
- 在對(duì)象轉(zhuǎn)換為原始值之后臭家,如果至少有一個(gè)操作數(shù)不是字符串,那么兩個(gè)操作數(shù)都將轉(zhuǎn)換為數(shù)字進(jìn)行述職比較方淤。0和-0相等钉赁。Infinity大于任何數(shù)字(除了自己)。-Infinity小于任何數(shù)字(除了自己)携茂。如果其中一個(gè)操作數(shù)是NaN(或轉(zhuǎn)換后是NaN)你踩,那么比較操作符總是返回false。
所有的大寫的ASCII字母都小魚(yú)小寫的ASCII字母讳苦。 'Zoo'<'apple'
返回true
in 運(yùn)算符
in運(yùn)算符希望它的左操作數(shù)是一個(gè)字符串還或可以轉(zhuǎn)換為字符串带膜,希望它的右操作數(shù)是一個(gè)對(duì)象。如果右側(cè)的對(duì)象擁有一個(gè)名為左操作數(shù)值得屬性名鸳谜,那么表達(dá)式返回true膝藕。
var point={x:1,y:2}; //定義一個(gè)對(duì)象
"x" in point; //true
"z" in point; //false
"toString" in point //true ,對(duì)象繼承了toString()方法
var data=[7,8,9];//定義一個(gè)數(shù)組
"0" in data; //true
1 in data; //true,數(shù)字轉(zhuǎn)換為字符串
3 in data; //false咐扭,不存在索引3的元素
"toString" in t //true芭挽,數(shù)組有toString()方法
instanceof 運(yùn)算符
instanceof運(yùn)算符希望左操作數(shù)是一個(gè)對(duì)象滑废,右操作數(shù)標(biāo)識(shí)對(duì)象的類。如果左側(cè)的對(duì)象是右側(cè)類的實(shí)例袜爪,則表達(dá)式返回true蠕趁,否則返回false。
var d = new Date();
d instanceof Date;//true
d instanceof Object; //true
d instanceof Number; //false
var a = [1, 2, 3];
a instanceof Array;//true
a instanceof Object; //true
a instanceof RegExp;//false
所有的對(duì)象都是Object的實(shí)例辛馆,當(dāng)通過(guò)instanceof判斷一個(gè)對(duì)象是否是一個(gè)類的實(shí)例的時(shí)候妻导,這個(gè)判斷也會(huì)對(duì)其父類檢測(cè)。
如果instanceof左操作數(shù)不是對(duì)象怀各,返回false倔韭。如果右操作數(shù)不是函數(shù),拋出類型錯(cuò)誤異常瓢对。
instanceof 工作原理(原型鏈prototype chain):原型鏈?zhǔn)荍avaScript的繼承機(jī)制寿酌。為了計(jì)算表達(dá)式 o instanceof f,JavaScript首先計(jì)算f.prototype硕蛹,然后在原型鏈中查找o醇疼,如果找到,那么o是f的一個(gè)實(shí)例法焰,表達(dá)式返回true秧荆。否則返回false。
邏輯表達(dá)式
&&
||
!
返回true埃仪,false乙濒。
&&
邏輯與
第一層理解:當(dāng)操作數(shù)都是布爾值的時(shí)候,返回true或false卵蛉。
假值:false颁股,null,undefined傻丝,0甘有,-0,NaN葡缰,""亏掀。所有其他的值包括所有對(duì)象都是真值。
第二層理解:對(duì)真值和假值進(jìn)行與操作泛释。在JavaScript中任何希望使用布爾值的地方滤愕,表達(dá)式和語(yǔ)句都會(huì)將其當(dāng)做真值或者假值來(lái)對(duì)待。因此并不總是返回true或false胁澳。
第三層理解:運(yùn)算符首先計(jì)算左操作數(shù)的值该互,如果是假值,則整個(gè)表達(dá)式也是假值韭畸。因此&&
返回左操作數(shù)的值宇智,而不會(huì)對(duì)右操作數(shù)進(jìn)行計(jì)算蔓搞。如果左操作數(shù)是假值,則表達(dá)式結(jié)果取決于右操作數(shù)的值随橘。&&
將計(jì)算右操作數(shù)的值并將其返回作為整個(gè)表達(dá)式的計(jì)算結(jié)果喂分。
> 1&&false
false
> 1&&true
true
> 1&&2
2
> 2&&1
1
> 0&&1
0
> true&&1
1
> false&&1
false
> true&&0
0
> var o={x:1}
undefined
> var p=null
undefined
> o&&o.x
1
> p&&p.x
null
&&
的行為有時(shí)被稱作“短路”。
if(a==b) stop();
(a==b) && stop();//二者等價(jià)
||
邏輯或
同&&
對(duì)比理解机蔗。
如果第一個(gè)操作數(shù)為真蒲祈,則返回真值。否則計(jì)算第二個(gè)操作數(shù)萝嘁,并返回表達(dá)式的計(jì)算結(jié)果梆掸。
> 1||NaN
1
> 0||NaN
NaN
!
邏輯非
!
是一元運(yùn)算符。將操作數(shù)的布爾值求反牙言。
首先將其操作數(shù)轉(zhuǎn)換為布爾值酸钦,然后在對(duì)布爾值求反,總是返回true或false咱枉,并且可以通過(guò)兩次邏輯非得到等價(jià)布爾值卑硫。!!x
。優(yōu)先級(jí)很高蚕断。
!(p&&q)===!p||!q
!(p||q)===!p&&!q
賦值表達(dá)式
=
運(yùn)算符希望它的左操作數(shù)是一個(gè)左值(變量欢伏、對(duì)象屬性或數(shù)組元素),右操作數(shù)是任意值亿乳。
賦值操作符的結(jié)合性是從右到左硝拧。
i=j=k=0; //把三個(gè)變量初始化為0
帶操作的賦值運(yùn)算
+=
-=
*=
/=
%=
<<=
>>=
>>>=
&=
|=
^=
大多數(shù)情況下,a op= b
等價(jià)于a = a op b
表達(dá)式計(jì)算
通過(guò)eval()
解釋運(yùn)行由JavaScript源代碼組成的字符串风皿,并產(chǎn)生一個(gè)值河爹。
eval("3+2") //5
eval()只有一個(gè)參數(shù)。如果參數(shù)不是字符串桐款,它直接返回此參數(shù)。如果參數(shù)是字符串夷恍,他會(huì)把字符串當(dāng)成JavaScript代碼進(jìn)行編譯魔眨。編譯失敗將拋出語(yǔ)法異常,編譯成功則執(zhí)行代碼酿雪,并返回字符串中的最后一個(gè)表達(dá)式或語(yǔ)句的值(如果最后一個(gè)表達(dá)式或語(yǔ)句沒(méi)有值遏暴,則最終返回undefined)。如果字符串拋出異常指黎,則異常將把該調(diào)用傳遞給eval()朋凉。
eval()查找變量的值和定義新變量和函數(shù)額操作與局部作用域中的代碼完全一樣。
注意:傳遞給eval()的字符串必須在語(yǔ)法上講得通醋安。不能通過(guò)eval()向函數(shù)中任意粘貼代碼片段杂彭。否則將拋出語(yǔ)法錯(cuò)誤異常墓毒。
var foo=function(a){
eval(a);
};
foo("return;");// SyntaxError: Illegal return statement
【全局eval實(shí)例】
var geval = eval;
var x = "global", y = "global";
function f() {
var x = "local";
eval("x += 'changed';"); //直接eval更改局部變量
return x;//返回修改后的局部變量
}
function g() {
var y = "local";
geval("y += 'changed';"); //間接調(diào)用改變?nèi)肿兞? return y;//返回未修改的局部變量
}
console.log(f(), x);//打印 "localchanged global"
console.log(g(), y);//打印 "local globalchanged"
嚴(yán)格eval()
use strict
嚴(yán)格模式將eval
列為保留字,不允許使用別名覆蓋eval()函數(shù)亲怠。并且變量名所计、函數(shù)名、函數(shù)參數(shù)或者異常捕獲的參數(shù)都不能取名為eval团秽。
其他運(yùn)算符
?:
條件運(yùn)算符
?:
是JavaScript中唯一的一個(gè)三元運(yùn)算符主胧。
條件操作符的操作數(shù)可以是任意類型。第一個(gè)操作數(shù)當(dāng)成布爾值习勤,如果真則計(jì)算第二個(gè)操作數(shù)并返回計(jì)算結(jié)果踪栋,如果假計(jì)算第三個(gè)操作數(shù)并返回計(jì)算結(jié)果。第二個(gè)和第三個(gè)操作數(shù)總是會(huì)計(jì)算其中之一图毕,不可能二者同時(shí)執(zhí)行夷都。(使用if語(yǔ)句也會(huì)帶來(lái)同樣效果)
greeting="hello"+(username?username:"there");
//上下二者等價(jià)
greeting="hello"
if(username)
greeting+=username;
else
greeting+="there";
typeof
運(yùn)算符
一元運(yùn)算符,放在其單個(gè)操作數(shù)的前面吴旋,操作數(shù)可以是任意類型损肛。返回操作數(shù)類型的一個(gè)字符串。
typeof x
typeof (x)
x | typeof x |
---|---|
undefined | "undefined" |
null | "object" |
true/false | "boolean" |
任意數(shù)字或NaN | "number" |
任意字符串 | "string" |
任意函數(shù) | "function" |
任意內(nèi)置對(duì)象(非函數(shù)) | "object" |
任意宿主對(duì)象 | 由編譯器各自實(shí)現(xiàn)的字符串荣瑟。但是不是"undefined" "boolean" "number" "string" |
delete
運(yùn)算符
一元運(yùn)算符治拿,刪除對(duì)象屬性或者數(shù)組元素。
var o={x:1;y:2};
delete o.x;
"x" in o;//false笆焰,這個(gè)屬性不再存在
var a=[1,2,3,4];
delete a[2];//刪除倒數(shù)第二個(gè)元素
2 in a;//false劫谅,這個(gè)元素不再存在
a[2];//undefined
a;// [1,2,,4]
a.length;// 4。刪除操作嚷掠,沒(méi)有修改數(shù)組長(zhǎng)度
delete希望他的操作數(shù)是一個(gè)左值捏检,如果不是左值,delete將不進(jìn)行任何操作并返回true不皆。否則贯城,delete駛?cè)雱h除這個(gè)指定的左值,如果刪除成功霹娄,返回true能犯,否則返回false。內(nèi)置核心和客戶端屬性是不能刪除的犬耻,用var語(yǔ)句生命的變量不能刪除踩晶,通過(guò)function語(yǔ)句定義的函數(shù)和函數(shù)參數(shù)也不能刪除。
> fff=function(){}
[Function: fff]
> typeof fff
'function'
> delete fff
true
> fff
ReferenceError: fff is not defined
> function ff(){}
undefined
> delete ff
false
> ff
[Function: ff]
ES5嚴(yán)格模式下枕磁,有操作數(shù)是一個(gè)屬性訪問(wèn)表達(dá)式才會(huì)正常工作渡蜻,否則將會(huì)拋出語(yǔ)法錯(cuò)誤。
void
運(yùn)算符
一元運(yùn)算符,它出現(xiàn)在操作數(shù)之前茸苇,操作數(shù)可以是任意類型排苍。操作數(shù)會(huì)照常計(jì)算,但忽略結(jié)果并返回undefined税弃。
最常用在客戶端的URL中纪岁。
<a href="javascript:void window.open();">打開(kāi)一個(gè)新窗口</a>
,
逗號(hào)運(yùn)算符
二元運(yùn)算符,操作數(shù)任意類型则果,先計(jì)算左操作數(shù)幔翰,再計(jì)算右操作數(shù),最后返回右操作數(shù)的值西壮。