javascript共提供10個(gè)算術(shù)運(yùn)算符
.加法運(yùn)算符:x + y
減法運(yùn)算符:x - y
乘法運(yùn)算符:x * y
除法運(yùn)算符:x / y
指數(shù)運(yùn)算符:x ** y
余數(shù)運(yùn)算符:x % y
自增運(yùn)算符:++x或者x++
自減運(yùn)算符:--x或者x--
數(shù)值運(yùn)算符:+x
負(fù)數(shù)值運(yùn)算符:-x
JavaScript允許非數(shù)值的相加待德。
true+true //2
1+true //2
上面代碼中的這兩種情況袋狞,布爾值都會(huì)自動(dòng)轉(zhuǎn)成數(shù)值师枣,然后再相加鸵钝。
比較特殊的是谒麦,如果是兩個(gè)字符串相加妹卿,這時(shí)加法運(yùn)算符會(huì)變成連接運(yùn)算符小染,返回一個(gè)新的字符串援岩,將兩個(gè)原字符串連接在一起。
如果一個(gè)運(yùn)算子是字符串锹锰,另一個(gè)運(yùn)算子是非字符串芥炭,這時(shí)非字符串會(huì)轉(zhuǎn)成字符串,再連接在一起恃慧。
加法運(yùn)算符是在運(yùn)行時(shí)決定园蝠,到底是執(zhí)行相加,還是執(zhí)行連接痢士。也就是說彪薛,運(yùn)算子的不同,導(dǎo)致了不同的語法行為怠蹂,這種現(xiàn)象稱為“重載”(overload)善延。由于加法運(yùn)算符存在重載,可能執(zhí)行兩種運(yùn)算城侧,使用的時(shí)候必須很小心易遣。
上面代碼中,由于從左到右的運(yùn)算次序嫌佑,字符串的位置不同會(huì)導(dǎo)致不同的結(jié)果豆茫。
除了加法運(yùn)算符,其他算術(shù)運(yùn)算符(比如減法歧强、除法和乘法)都不會(huì)發(fā)生重載澜薄。它們的規(guī)則是:所有運(yùn)算子一律轉(zhuǎn)為數(shù)值,再進(jìn)行相應(yīng)的數(shù)學(xué)運(yùn)算摊册。
對(duì)象的相加
如果運(yùn)算子是對(duì)象肤京,必須先轉(zhuǎn)成原始類型的值,然后再相加茅特。
上面代碼中忘分,對(duì)象obj轉(zhuǎn)成原始類型的值是[object Object],再加2就得到了上面的結(jié)果白修。
對(duì)象轉(zhuǎn)成原始類型的值妒峦,規(guī)則如下。
首先兵睛,自動(dòng)調(diào)用對(duì)象的valueOf方法肯骇。
一般來說窥浪,對(duì)象的valueOf方法總是返回對(duì)象自身,這時(shí)再自動(dòng)調(diào)用對(duì)象的toString方法笛丙,將其轉(zhuǎn)為字符串漾脂。
對(duì)象的toString方法默認(rèn)返回[object Object]。
知道了這個(gè)規(guī)則以后胚鸯,就可以自己定義valueOf方法或toString方法骨稿,得到想要的結(jié)果。
這個(gè)例子中姜钳,由于valueOf方法直接返回一個(gè)原始類型的值坦冠,所以不再調(diào)用toString方法。
下面是自定義toString方法的例子哥桥。
這里有一個(gè)特例辙浑,如果運(yùn)算子是一個(gè)Date對(duì)象的實(shí)例,那么會(huì)優(yōu)先執(zhí)行toString方法
余數(shù)運(yùn)算符
余數(shù)運(yùn)算符(%)返回前一個(gè)運(yùn)算子被后一個(gè)運(yùn)算子除泰讽,所得的余數(shù)例衍。需要注意的是昔期,運(yùn)算結(jié)果的正負(fù)號(hào)由第一個(gè)運(yùn)算子的正負(fù)號(hào)決定已卸。
所以,為了得到負(fù)數(shù)的正確余數(shù)值硼一,可以先使用絕對(duì)值函數(shù)累澡。Math.abs()
余數(shù)運(yùn)算符還可以用于浮點(diǎn)數(shù)的運(yùn)算。但是般贼,由于浮點(diǎn)數(shù)不是精確的值愧哟,無法得到完全準(zhǔn)確的結(jié)果。
自增和自減運(yùn)算符
自增和自減運(yùn)算符哼蛆,是一元運(yùn)算符蕊梧,只需要一個(gè)運(yùn)算子。它們的作用是將運(yùn)算子首先轉(zhuǎn)為數(shù)值腮介,然后加上1或者減去1肥矢。它們會(huì)修改原始變量。
上面代碼的變量x自增后叠洗,返回2甘改,再進(jìn)行自減,返回1灭抑。這兩種情況都會(huì)使得十艾,原始變量x的值發(fā)生改變。
運(yùn)算之后腾节,變量的值發(fā)生變化忘嫉,這種效應(yīng)叫做運(yùn)算的副作用荤牍。自增和自減運(yùn)算符是僅有的兩個(gè)具有副作用的運(yùn)算符,其他運(yùn)算符都不會(huì)改變變量的值庆冕。
自增和自減運(yùn)算符有一個(gè)需要注意的地方参淫,就是放在變量之后,會(huì)先返回變量操作前的值愧杯,再進(jìn)行自增/自減操作涎才;放在變量之前,會(huì)先進(jìn)行自增/自減操作力九,再返回變量操作后的值耍铜。
上面代碼中,x是先返回當(dāng)前值跌前,然后自增棕兼,所以得到1;y是先自增抵乓,然后返回新的值伴挚,所以得到2。
數(shù)值運(yùn)算符灾炭,負(fù)數(shù)值運(yùn)算符
數(shù)值運(yùn)算符(+)同樣使用加號(hào)茎芋,但它是一元運(yùn)算符(只需要一個(gè)操作數(shù)),而加法運(yùn)算符是二元運(yùn)算符(需要兩個(gè)操作數(shù))蜈出。
數(shù)值運(yùn)算符的作用在于可以將任何值轉(zhuǎn)為數(shù)值(與Number函數(shù)的作用相同)
上面代碼表示田弥,非數(shù)值經(jīng)過數(shù)值運(yùn)算符以后,都變成了數(shù)值(最后一行NaN也是數(shù)值)铡原。
負(fù)數(shù)值運(yùn)算符(-)偷厦,也同樣具有將一個(gè)值轉(zhuǎn)為數(shù)值的功能,只不過得到的值正負(fù)相反燕刻。連用兩個(gè)負(fù)數(shù)值運(yùn)算符只泼,等同于數(shù)值運(yùn)算符。
上面代碼最后一行的圓括號(hào)不可少卵洗,否則會(huì)變成自減運(yùn)算符请唱。
數(shù)值運(yùn)算符號(hào)和負(fù)數(shù)值運(yùn)算符,都會(huì)返回一個(gè)新的值忌怎,而不會(huì)改變?cè)甲兞康闹怠?/p>
賦值運(yùn)算符
賦值運(yùn)算符用于給變量賦值。
賦值運(yùn)算符還可以與其他運(yùn)算符結(jié)合,形成變體鸥印。下面是與算術(shù)運(yùn)算符的結(jié)合勋功。
比較運(yùn)算符
比較運(yùn)算符用于比較兩個(gè)值的大小坦报,然后返回一個(gè)布爾值,表示是否滿足指定的條件狂鞋。
非相等運(yùn)算符:字符串的比較
非相等運(yùn)算符:非字符串的比較
如果兩個(gè)運(yùn)算子之中,至少有一個(gè)不是字符串骚揍,需要分成以下兩種情況字管。
1.原始類型值
如果兩個(gè)運(yùn)算子都是原始類型的值,則是先轉(zhuǎn)成數(shù)值再比較信不。
這里需要注意與NaN的比較嘲叔。任何值(包括NaN本身)與NaN比較,返回的都是false抽活。(#任何值和NaN比都返回NaN)
2.對(duì)象
運(yùn)算子是對(duì)象硫戈,會(huì)轉(zhuǎn)為原始類型的值,再進(jìn)行比較下硕。
對(duì)象轉(zhuǎn)換成原始類型的值丁逝,算法是先調(diào)用valueOf方法;如果返回的還是對(duì)象梭姓,再接著調(diào)用toString方法霜幼。
嚴(yán)格相等運(yùn)算符
JavaScript 提供兩種相等運(yùn)算符:==和===。
簡(jiǎn)單說糊昙,它們的區(qū)別是相等運(yùn)算符(==)比較兩個(gè)值是否相等辛掠,嚴(yán)格相等運(yùn)算符(===)比較它們是否為“同一個(gè)值”谢谦。如果兩個(gè)值不是同一類型释牺,嚴(yán)格相等運(yùn)算符(===)直接返回false,而相等運(yùn)算符(==)會(huì)將它們轉(zhuǎn)換成同一個(gè)類型回挽,再用嚴(yán)格相等運(yùn)算符進(jìn)行比較没咙。
1.不同類型的值
如果兩個(gè)值的類型不同,直接返回false千劈。2.同一類的原始類型值
上面代碼比較十進(jìn)制的1與十六進(jìn)制的1祭刚,因?yàn)轭愋秃椭刀枷嗤祷豻rue墙牌。
需要注意的是涡驮,NaN與任何值都不相等(包括自身)。另外喜滨,正0等于負(fù)0捉捅。
3.復(fù)合類型值
兩個(gè)復(fù)合類型(對(duì)象、數(shù)組虽风、函數(shù))的數(shù)據(jù)比較時(shí)棒口,不是比較它們的值是否相等寄月,而是比較它們是否指向同一個(gè)地址。
上面代碼分別比較兩個(gè)空對(duì)象无牵、兩個(gè)空數(shù)組漾肮、兩個(gè)空函數(shù),結(jié)果都是不相等茎毁。原因是對(duì)于復(fù)合類型的值克懊,嚴(yán)格相等運(yùn)算比較的是,它們是否引用同一個(gè)內(nèi)存地址七蜘,而運(yùn)算符兩邊的空對(duì)象保檐、空數(shù)組、空函數(shù)的值崔梗,都存放在不同的內(nèi)存地址夜只,結(jié)果當(dāng)然是false。
注意蒜魄,對(duì)于兩個(gè)對(duì)象的比較扔亥,嚴(yán)格相等運(yùn)算符比較的是地址,而大于或小于運(yùn)算符比較的是值谈为。
4.undefined 和 null
undefined和null與自身嚴(yán)格相等由于變量聲明后默認(rèn)值是undefined旅挤,因此兩個(gè)只聲明未賦值的變量是相等的。
嚴(yán)格不相等運(yùn)算符
嚴(yán)格相等運(yùn)算符有一個(gè)對(duì)應(yīng)的“嚴(yán)格不相等運(yùn)算符”(!==)伞鲫,它的算法就是先求嚴(yán)格相等運(yùn)算符的結(jié)果粘茄,然后返回相反值。
上面代碼中秕脓,感嘆號(hào)!是求出后面表達(dá)式的相反值柒瓣。
相等運(yùn)算符
相等運(yùn)算符用來比較相同類型的數(shù)據(jù)時(shí),與嚴(yán)格相等運(yùn)算符完全一樣吠架。比較不同類型的數(shù)據(jù)時(shí)芙贫,相等運(yùn)算符會(huì)先將數(shù)據(jù)進(jìn)行類型轉(zhuǎn)換,然后再用嚴(yán)格相等運(yùn)算符比較傍药。下面分成四種情況送丰,討論不同類型的值互相比較的規(guī)則攻旦。
1.原始類型值
原始類型的值會(huì)轉(zhuǎn)換成數(shù)值再進(jìn)行比較。
2.對(duì)象與原始類型值比較
對(duì)象(這里指廣義的對(duì)象,包括數(shù)組和函數(shù))與原始類型的值比較時(shí)状婶,對(duì)象轉(zhuǎn)換成原始類型的值霸妹,再進(jìn)行比較瞻赶。面代碼中维雇,數(shù)組[1]與數(shù)值進(jìn)行比較,會(huì)先轉(zhuǎn)成數(shù)值乙埃,再進(jìn)行比較闸英;與字符串進(jìn)行比較锯岖,會(huì)先轉(zhuǎn)成字符串,再進(jìn)行比較甫何;與布爾值進(jìn)行比較出吹,對(duì)象和布爾值都會(huì)先轉(zhuǎn)成數(shù)值,再進(jìn)行比較辙喂。
3.undefined 和 null
undefined和null與其他類型的值比較時(shí)捶牢,結(jié)果都為false,它們互相比較時(shí)結(jié)果為true巍耗。
4.相等運(yùn)算符的缺點(diǎn)
相等運(yùn)算符隱藏的類型轉(zhuǎn)換秋麸,會(huì)帶來一些違反直覺的結(jié)果。上面這些表達(dá)式都不同于直覺炬太,很容易出錯(cuò)灸蟆。因此建議不要使用相等運(yùn)算符(==),最好只使用嚴(yán)格相等運(yùn)算符(===)亲族。
不相等運(yùn)算符
相等運(yùn)算符有一個(gè)對(duì)應(yīng)的“不相等運(yùn)算符”(!=)炒考,它的算法就是先求相等運(yùn)算符的結(jié)果,然后返回相反值霎迫。
布爾運(yùn)算符
概述
布爾運(yùn)算符用于將表達(dá)式轉(zhuǎn)為布爾值斋枢,一共包含四個(gè)運(yùn)算符。
取反運(yùn)算符:!
且運(yùn)算符:&&
或運(yùn)算符:||
三元運(yùn)算符:?:
取反運(yùn)算符(!)
取反運(yùn)算符是一個(gè)感嘆號(hào)知给,用于將布爾值變?yōu)橄喾粗等恐悖磘rue變成false,false變成true涩赢。
對(duì)于非布爾值戈次,取反運(yùn)算符會(huì)將其轉(zhuǎn)為布爾值≮酥鳎可以這樣記憶朝扼,以下六個(gè)值取反后為true,其他值都為false霎肯。
且運(yùn)算符(&&)
且運(yùn)算符(&&)往往用于多個(gè)表達(dá)式的求值。
它的運(yùn)算規(guī)則是:如果第一個(gè)運(yùn)算子的布爾值為true榛斯,則返回第二個(gè)運(yùn)算子的值(注意是值观游,不是布爾值);如果第一個(gè)運(yùn)算子的布爾值為false驮俗,則直接返回第一個(gè)運(yùn)算子的值懂缕,且不再對(duì)第二個(gè)運(yùn)算子求值。
上面代碼的最后一個(gè)例子王凑,由于且運(yùn)算符的第一個(gè)運(yùn)算子的布爾值為false搪柑,則直接返回它的值0聋丝,而不再對(duì)第二個(gè)運(yùn)算子求值,所以變量x的值沒變工碾。
這種跳過第二個(gè)運(yùn)算子的機(jī)制弱睦,被稱為“短路”。有些程序員喜歡用它取代if結(jié)構(gòu)渊额,比如下面是一段if結(jié)構(gòu)的代碼况木,就可以用且運(yùn)算符改寫。且運(yùn)算符可以多個(gè)連用旬迹,這時(shí)返回第一個(gè)布爾值為false的表達(dá)式的值火惊。如果所有表達(dá)式的布爾值都為true,則返回最后一個(gè)表達(dá)式的值奔垦。
或運(yùn)算符(||)
或運(yùn)算符(||)也用于多個(gè)表達(dá)式的求值屹耐。它的運(yùn)算規(guī)則是:如果第一個(gè)運(yùn)算子的布爾值為true,則返回第一個(gè)運(yùn)算子的值椿猎,且不再對(duì)第二個(gè)運(yùn)算子求值张症;如果第一個(gè)運(yùn)算子的布爾值為false,則返回第二個(gè)運(yùn)算子的值鸵贬。短路規(guī)則對(duì)這個(gè)運(yùn)算符也適用俗他。
上面代碼中,或運(yùn)算符的第一個(gè)運(yùn)算子為true阔逼,所以直接返回true兆衅,不再運(yùn)行第二個(gè)運(yùn)算子。所以嗜浮,x的值沒有改變羡亩。這種只通過第一個(gè)表達(dá)式的值,控制是否運(yùn)行第二個(gè)表達(dá)式的機(jī)制危融,就稱為“短路”畏铆。
或運(yùn)算符可以多個(gè)連用,這時(shí)返回第一個(gè)布爾值為true的表達(dá)式的值吉殃。如果所有表達(dá)式都為false辞居,則返回最后一個(gè)表達(dá)式的值。
或運(yùn)算符常用于為一個(gè)變量設(shè)置默認(rèn)值蛋勺。
上面代碼表示瓦灶,如果函數(shù)調(diào)用時(shí),沒有提供參數(shù)抱完,則該參數(shù)默認(rèn)設(shè)置為空字符串贼陶。
三元條件運(yùn)算符(?:)
三元條件運(yùn)算符由問號(hào)(?)和冒號(hào)(:)組成,分隔三個(gè)表達(dá)式。它是JavaScript語言唯一一個(gè)需要三個(gè)運(yùn)算子的運(yùn)算符碉怔。如果第一個(gè)表達(dá)式的布爾值為true烘贴,則返回第二個(gè)表達(dá)式的值,否則返回第三個(gè)表達(dá)式的值撮胧。
通常來說桨踪,三元條件表達(dá)式與if...else語句具有同樣表達(dá)效果,前者可以表達(dá)的趴樱,后者也能表達(dá)馒闷。但是兩者具有一個(gè)重大差別,if...else是語句叁征,沒有返回值纳账;三元條件表達(dá)式是表達(dá)式,具有返回值捺疼。所以疏虫,在需要返回值的場(chǎng)合,只能使用三元條件表達(dá)式啤呼,而不能使用if..else卧秘。
上面代碼中,console.log方法的參數(shù)必須是一個(gè)表達(dá)式官扣,這時(shí)就只能使用三元條件表達(dá)式翅敌。如果要用if...else語句,就必須改變整個(gè)代碼寫法了惕蹄。
其他運(yùn)算符蚯涮,運(yùn)算順序
void 運(yùn)算符
void運(yùn)算符的作用是執(zhí)行一個(gè)表達(dá)式,然后不返回任何值卖陵,或者說返回undefined遭顶。上面是void運(yùn)算符的兩種寫法,都正確泪蔫。建議采用后一種形式棒旗,即總是使用圓括號(hào)。因?yàn)関oid運(yùn)算符的優(yōu)先性很高撩荣,如果不使用括號(hào)铣揉,容易造成錯(cuò)誤的結(jié)果。比如婿滓,void 4 + 7實(shí)際上等同于(void 4) + 7老速。
下面是void運(yùn)算符的一個(gè)例子。這個(gè)運(yùn)算符的主要用途是瀏覽器的書簽工具凸主,以及在超級(jí)鏈接中插入代碼防止網(wǎng)頁(yè)跳轉(zhuǎn)。
image.png
面代碼中额湘,點(diǎn)擊鏈接后卿吐,會(huì)先執(zhí)行onclick的代碼旁舰,由于onclick返回false,所以瀏覽器不會(huì)跳轉(zhuǎn)到example.com嗡官。
void運(yùn)算符可以取代上面的寫法箭窜。下面是一個(gè)更實(shí)際的例子,用戶點(diǎn)擊鏈接提交表單衍腥,但是不產(chǎn)生頁(yè)面跳轉(zhuǎn)磺樱。
逗號(hào)運(yùn)算符
逗號(hào)運(yùn)算符用于對(duì)兩個(gè)表達(dá)式求值,并返回后一個(gè)表達(dá)式的值婆咸。逗號(hào)運(yùn)算符的一個(gè)用途是竹捉,在返回一個(gè)值之前,進(jìn)行一些輔助操作
image.png
運(yùn)算順序
優(yōu)先級(jí)
JavaScript各種運(yùn)算符的優(yōu)先級(jí)別是不一樣的尚骄。優(yōu)先級(jí)高的運(yùn)算符先執(zhí)行块差,優(yōu)先級(jí)低的運(yùn)算符后執(zhí)行。上面的代碼中倔丈,乘法運(yùn)算符(*)的優(yōu)先性高于加法運(yùn)算符(+)憨闰,所以先執(zhí)行乘法,再執(zhí)行加法需五,相當(dāng)于下面這樣鹉动。
圓括號(hào)的作用
圓括號(hào)(())可以用來提高運(yùn)算的優(yōu)先級(jí)泽示,因?yàn)樗膬?yōu)先級(jí)是最高的,即圓括號(hào)中的表達(dá)式會(huì)第一個(gè)運(yùn)算蜀铲。運(yùn)算符的優(yōu)先級(jí)別十分繁雜边琉,且都是硬性規(guī)定,因此建議總是使用圓括號(hào)记劝,保證運(yùn)算順序清晰可讀变姨,這對(duì)代碼的維護(hù)和除錯(cuò)至關(guān)重要。
順便說一下厌丑,圓括號(hào)不是運(yùn)算符定欧,而是一種語法結(jié)構(gòu)。它一共有兩種用法:一種是把表達(dá)式放在圓括號(hào)之中怒竿,提升運(yùn)算的優(yōu)先級(jí)砍鸠;另一種是跟在函數(shù)的后面,作用是調(diào)用函數(shù)耕驰。
注意爷辱,因?yàn)閳A括號(hào)不是運(yùn)算符,所以不具有求值作用,只改變運(yùn)算的優(yōu)先級(jí)饭弓。
上面代碼的第二行双饥,如果圓括號(hào)具有求值作用,那么就會(huì)變成1 = 2弟断,這是會(huì)報(bào)錯(cuò)了咏花。但是,上面的代碼可以運(yùn)行阀趴,這驗(yàn)證了圓括號(hào)只改變優(yōu)先級(jí)昏翰,不會(huì)求值。
這也意味著刘急,如果整個(gè)表達(dá)式都放在圓括號(hào)之中棚菊,那么不會(huì)有任何效果。
函數(shù)放在圓括號(hào)中排霉,會(huì)返回函數(shù)本身窍株。如果圓括號(hào)緊跟在函數(shù)的后面,就表示調(diào)用函數(shù)攻柠。
圓括號(hào)之中球订,只能放置表達(dá)式,如果將語句放在圓括號(hào)之中瑰钮,就會(huì)報(bào)錯(cuò)冒滩。
左結(jié)合與右結(jié)合
對(duì)于優(yōu)先級(jí)別相同的運(yùn)算符,大多數(shù)情況浪谴,計(jì)算順序總是從左到右开睡,這叫做運(yùn)算符的“左結(jié)合”,即從左邊開始計(jì)算苟耻。
上面代碼先計(jì)算最左邊的x與y的和篇恒,然后再計(jì)算與z的和。
是少數(shù)運(yùn)算符的計(jì)算順序是從右到左凶杖,即從右邊開始計(jì)算胁艰,這叫做運(yùn)算符的“右結(jié)合”。其中智蝠,最主要的是賦值運(yùn)算符(=)和三元條件運(yùn)算符(?:)腾么。
上面代碼的運(yùn)算結(jié)果,相當(dāng)于下面的樣子杈湾。
指數(shù)運(yùn)算符(**)也是右結(jié)合的解虱。
**也就是說指數(shù) 賦值 和三元條件運(yùn)算符是右邊結(jié)合**