摘要:函數(shù)定義表達(dá)式。對象創(chuàng)建表達(dá)式。也就是說,空字符串將被當(dāng)作,布爾值將被當(dāng)作。如果有一個(gè)操作數(shù)是對象數(shù)值或布爾值,則調(diào)用它們的方法取得相應(yīng)的字符串值,然后再應(yīng)用前面關(guān)于字符串的規(guī)則。對于和,則分別調(diào)用函數(shù)并取得字符串和。
表達(dá)式
表達(dá)式是由數(shù)字、運(yùn)算符、數(shù)字分組符號(如括號)、自由變量和約束變量等以能求得數(shù)值的有意義排列方法所得的組合。JavaScript 表達(dá)式主要有以下幾種形式:
原始表達(dá)式:常量、變量、保留字。
對象、數(shù)組初始化表達(dá)式:var obj={a:1,b:2};,var arr=[1,2,3];。
函數(shù)定義表達(dá)式:var fn=function(){}。
屬性訪問表達(dá)式:Math.abs。
調(diào)用表達(dá)式:alert("hello");。
對象創(chuàng)建表達(dá)式:new object();。
運(yùn)算符JavaScript 中的運(yùn)算符用于算術(shù)表達(dá)式、比較表達(dá)式、邏輯表達(dá)式、賦值表達(dá)式等。需要注意的是,大多數(shù)運(yùn)算符都是由標(biāo)點(diǎn)符號表示的,比如 + 和 =。而另外一些運(yùn)算符則是由關(guān)鍵字表示的,比如 typeof 和 instanceof,關(guān)鍵字運(yùn)算符和標(biāo)點(diǎn)符號都是正規(guī)的運(yùn)算符。
下表列出了 JavaScript 中所有的運(yùn)算符,并按照運(yùn)算符的優(yōu)先級排序的,前面的運(yùn)算符優(yōu)先級要高于后面的運(yùn)算符優(yōu)先級,被空行分隔開來的運(yùn)算符具有不同的優(yōu)先級。標(biāo)題為 A 的列表示運(yùn)算符的結(jié)合性(Associativity),L 表示從左至右、R 表示從右至左,標(biāo)題為 N 的列表示操作數(shù)的個(gè)數(shù)(Number)。
運(yùn)算符 | 操作 | A | N |
---|---|---|---|
++ | 前/后增量 | R | 1 |
-- | 前/后增量 | R | 1 |
- | 求反 | R | 1 |
+ | 轉(zhuǎn)換為數(shù)字 | R | 1 |
~ | 按位求反 | R | 1 |
! | 邏輯非 | R | 1 |
delete | 刪除屬性 | R | 1 |
typeof | 檢測類型 | R | 1 |
void | 返回undefined | R | 1 |
* / % | 乘,除,求模 | L | 2 |
+ - | 加,減 | L | 2 |
+ | 字符串連接 | L | 2 |
<< | 左移位 | L | 2 |
>> | 有符號右移 | L | 2 |
>>> | 無符號右移 | L | 2 |
< <= > >= | 比較數(shù)字順序 | L | 2 |
< <= > >= | 比較字母順序 | L | 2 |
instanceof | 測試對象類 | L | 2 |
in | 測試屬性是否存在 | L | 2 |
== | 判斷相等 | L | 2 |
!= | 判斷不等 | L | 2 |
=== | 判斷恒等 | L | 2 |
!== | 判斷恒不等 | L | 2 |
& | 按位與 | L | 2 |
^ | 按位異或 | L | 2 |
┃ | 按位或 | L | 2 |
&& | 邏輯與 | L | 2 |
┃┃ | 邏輯或 | L | 2 |
?: | 條件運(yùn)算符 | R | 3 |
= | 賦值 | R | 2 |
*= /= %= += -= &= <<= >>= ^= ┃= >>>= |
運(yùn)算且賦值 | R | 2 |
, | 忽略第一個(gè)操作數(shù), 返回第二個(gè)操作數(shù) |
L | 2 |
一元運(yùn)算符 delete 運(yùn)算符因?yàn)?| 是制表符,會導(dǎo)致格式混亂,所以表格中的 | 均以 ┃ 代替。
delete 運(yùn)算符用來刪除對象屬性或者數(shù)組元素,如果刪除成功或所刪除的目標(biāo)不存在,delete 將返回 true。然而,并不是所有的屬性都可刪除,一些內(nèi)置核心和客戶端屬性是不能刪除的,通過 var 語句聲明的變量不能刪除,通過 function 語句定義的函數(shù)也是不能刪除的。例如:
var o = { x: 1, y: 2}; // 定義一個(gè)對象 console.log(delete o.x); // true,刪除一個(gè)屬性 console.log(delete o.x); // true,什么都沒做,x 在已上一步被刪除 console.log("x" in o); // false,這個(gè)屬性在對象中不再存在 console.log(delete o.toString); // true,什么也沒做,toString是繼承來的 console.log(delete 1); // true,無意義 var a = [1,2,3]; // 定義一個(gè)數(shù)組 console.log(delete a[2]); // true,刪除最后一個(gè)數(shù)組元素 console.log(2 in a); // false,元素2在數(shù)組中不再存在 console.log(a.length); // 3,數(shù)組長度并不會因 delete 而改變 console.log(a[2]); // undefined,元素2所在的位置被空了出來 console.log(delete a); // false,通過 var 語句聲明的變量不能刪除 function f(args){} // 定義一個(gè)函數(shù) console.log(delete f); // false,通過 function 語句聲明的函數(shù)不能刪除void 運(yùn)算符
void 運(yùn)算符可以應(yīng)用于任何表類型的表達(dá)式,表達(dá)式會被執(zhí)行,但計(jì)算結(jié)果會被忽略并返回 undefined。例如:
void 0; void "you are useless?"; void false; void []; void /(useless)/ig; void function(){ console.log("you are so useless?"); } // always return undefined
typeof 運(yùn)算符擴(kuò)展閱讀「談?wù)?JavaScript 中的 void 運(yùn)算符」
https://segmentfault.com/a/11...
++ -- 運(yùn)算符請參見「變量和數(shù)據(jù)類型」-「數(shù)據(jù)類型」-「typeof 運(yùn)算符」。
++ -- 遞增遞減運(yùn)算符借鑒自 C 語言,它們分前置型和后置型,作用是改變一個(gè)變量的值。例如:
var a = 5; console.log(a++); // 5 console.log(++a); // 7 console.log(a--); // 7 console.log(--a); // 5+ - 運(yùn)算符
當(dāng) + - 作為一元運(yùn)算符時(shí),應(yīng)用于數(shù)值,表示數(shù)值的正負(fù)。應(yīng)用于非數(shù)值,先按 Number() 轉(zhuǎn)型函數(shù)對這個(gè)值執(zhí)行轉(zhuǎn)換,再表示該值的正負(fù)。
~ ! 運(yùn)算符乘性運(yùn)算符~ 按位非運(yùn)算符,請參見下面「位運(yùn)算符」。
! 邏輯非運(yùn)算符,請參見下面「邏輯運(yùn)算符」。
JavaScript 定義了3個(gè)乘性運(yùn)算符:乘法、除法和求模。這些運(yùn)算符與 C 語言的相應(yīng)運(yùn)算符用途類似,只不過在操作數(shù)為非數(shù)值的情況下會執(zhí)行自動的類型轉(zhuǎn)換。如果參與乘法計(jì)算的某個(gè)操作數(shù)不是數(shù)值,后臺會先使用 Number() 轉(zhuǎn)型函數(shù)將其轉(zhuǎn)換為數(shù)值。也就是說,空字符串將被當(dāng)作 0,布爾值 true 將被當(dāng)作 1。
* 乘法運(yùn)算符用于計(jì)算兩個(gè)數(shù)值的乘積,在處理特殊值的情況下,乘法運(yùn)算符遵循下列特殊的規(guī)則:
如果操作數(shù)都是數(shù)值,執(zhí)行常規(guī)的乘法計(jì)算,即兩個(gè)正數(shù)或兩個(gè)負(fù)數(shù)相乘的結(jié)果還是正數(shù),而如果只有一個(gè)操作數(shù)有符號,那么結(jié)果就是負(fù)數(shù)。如果乘積超過了 JavaScript 數(shù)值的表示范圍,則返回 Infinity 或 -Infinity;
如果有一個(gè)操作數(shù)是 NaN,則結(jié)果是 NaN;
如果是 Infinity 與 0 相乘,則結(jié)果是 NaN;
如果是 Infinity 與非 0 數(shù)值相乘,則結(jié)果是 Infinity 或 -Infinity,取決于有符號操作數(shù)的符號;
如果是 Infinity 與 Infinity 相乘,則結(jié)果是 Infinity;
如果有一個(gè)操作數(shù)不是數(shù)值,則在后臺調(diào)用 Number()將其轉(zhuǎn)換為數(shù)值,然后再應(yīng)用上面的規(guī)則。
用于計(jì)算兩個(gè)數(shù)值的商,與乘法運(yùn)算符類似,除法運(yùn)算符對特殊的值也有特殊的處理規(guī)則。這些規(guī)則如下:
如果操作數(shù)都是數(shù)值,執(zhí)行常規(guī)的除法計(jì)算,即兩個(gè)正數(shù)或兩個(gè)負(fù)數(shù)相除的結(jié)果還是正數(shù),而如果只有一個(gè)操作數(shù)有符號,那么結(jié)果就是負(fù)數(shù)。如果商超過了 JavaScript 數(shù)值的表示范圍,則返回 Infinity 或 -Infinity;
如果有一個(gè)操作數(shù)是 NaN,則結(jié)果是 NaN;
如果是 Infinity 被 Infinity 除,則結(jié)果是 NaN;
如果是零被零除,則結(jié)果是 NaN;
如果是非零的有限數(shù)被零除,則結(jié)果是 Infinity 或 -Infinity,取決于有符號操作數(shù)的符號;
如果是 Infinity 被任何非零數(shù)值除,則結(jié)果是 Infinity 或 -Infinity,取決于有符號操作數(shù)的符號;
如果有一個(gè)操作數(shù)不是數(shù)值,則在后臺調(diào)用 Number() 將其轉(zhuǎn)換為數(shù)值,然后再應(yīng)用上面的規(guī)則。
% 求模運(yùn)算符用于計(jì)算兩個(gè)數(shù)值的余數(shù),與另外兩個(gè)乘性運(yùn)算符類似,求模運(yùn)算符會遵循下列特殊規(guī)則來處理特殊的值:
如果操作數(shù)都是數(shù)值,執(zhí)行常規(guī)的除法計(jì)算,返回除得的余數(shù);
如果被除數(shù)是無窮大值而除數(shù)是有限大的數(shù)值,則結(jié)果是 NaN;
如果被除數(shù)是有限大的數(shù)值而除數(shù)是零,則結(jié)果是 NaN;
如果是 Infinity 被 Infinity 除,則結(jié)果是 NaN;
如果被除數(shù)是有限大的數(shù)值而除數(shù)是無窮大的數(shù)值,則結(jié)果是被除數(shù);
如果被除數(shù)是零,則結(jié)果是零;
如果有一個(gè)操作數(shù)不是數(shù)值,則在后臺調(diào)用 Number() 將其轉(zhuǎn)換為數(shù)值,然后再應(yīng)用上面的規(guī)則。
加性運(yùn)算符加法和減法這兩個(gè)加性運(yùn)算符應(yīng)該說是編程語言中最簡單的算術(shù)運(yùn)算符了。但是在 JavaScript 中,這兩個(gè)運(yùn)算符卻都有一系列的特殊行為。與乘性運(yùn)算符類似,加性運(yùn)算符也會在后臺轉(zhuǎn)換不同的數(shù)據(jù)類型。然而,對于加性運(yùn)算符而言,相應(yīng)的轉(zhuǎn)換規(guī)則還稍微有點(diǎn)復(fù)雜。
+ 加法運(yùn)算符如果兩個(gè)運(yùn)算符都是數(shù)值,執(zhí)行常規(guī)的加法計(jì)算,然后根據(jù)下列規(guī)則返回結(jié)果:
如果有一個(gè)操作數(shù)是 NaN,則結(jié)果是 NaN;
如果是 Infinity 加 Infinity,則結(jié)果是 Infinity;
如果是 -Infinity 加 -Infinity,則結(jié)果是 -Infinity;
如果是 Infinity 加- Infinity,則結(jié)果是 NaN;
如果是 +0 加 +0,則結(jié)果是 +0;
如果是 -0 加 -0,則結(jié)果是 -0;
如果是 +0 加 -0,則結(jié)果是 +0;
如果有一個(gè)操作數(shù)不是數(shù)值,那么就要應(yīng)用如下規(guī)則:
如果兩個(gè)操作數(shù)都是字符串,則將第二個(gè)操作數(shù)與第一個(gè)操作數(shù)拼接起來;
如果只有一個(gè)操作數(shù)是字符串,則將另一個(gè)操作數(shù)轉(zhuǎn)換為字符串,然后再將兩個(gè)字符串拼接起來。
如果有一個(gè)操作數(shù)是對象、數(shù)值或布爾值,則調(diào)用它們的 toString() 方法取得相應(yīng)的字符串值,然后再應(yīng)用前面關(guān)于字符串的規(guī)則。對于 undefined 和 null,則分別調(diào)用 String() 函數(shù)并取得字符串 "undefined" 和 "null"。
如果是 null 加 null,則結(jié)果是 0;
如果是 undefined 加 undefined,則結(jié)果是 NaN;
下面來舉幾個(gè)例子:
var result1 = 5 + 5; // 兩個(gè)數(shù)值相加 console.log(result1); // 10 var result2 = 5 + "5"; // 一個(gè)數(shù)值和一個(gè)字符串相加 console.log(result2); // "55" var num1 = 5; var num2 = 10; var message = "The sum of 5 and 10 is " + num1 + num2; console.log(message); // "The sum of 5 and 10 is 510",如何修改?- 減法運(yùn)算符
如果兩個(gè)運(yùn)算符都是數(shù)值,執(zhí)行常規(guī)的減法計(jì)算,然后根據(jù)下列規(guī)則返回結(jié)果:
如果有一個(gè)操作數(shù)是 NaN,則結(jié)果是 NaN;
如果是 Infinity 減 Infinity,則結(jié)果是 NaN;
如果是 -Infinity 減 -Infinity,則結(jié)果是 NaN;
如果是 Infinity 減 -Infinity,則結(jié)果是 Infinity;
如果是 -Infinity 減 Infinity,則結(jié)果是 -Infinity;
如果是 +0 減 +0,則結(jié)果是 +0;
如果是 +0 減 -0,則結(jié)果是 -0;
如果是 -0 減 -0,則結(jié)果是 +0;
如果有一個(gè)操作數(shù)不是數(shù)值,那么就要應(yīng)用如下規(guī)則:
如果有一個(gè)操作數(shù)是字符串、布爾值、null 或 undefined,則先在后臺調(diào)用 Number() 函數(shù)將其轉(zhuǎn)換為數(shù)值,然后再根據(jù)前面的規(guī)則執(zhí)行減法計(jì)算。如果轉(zhuǎn)換的結(jié)果是 NaN,則減法的結(jié)果就是 NaN;
如果有一個(gè)操作數(shù)是對象,則調(diào)用對象的 valueOf() 方法以取得表示該對象的數(shù)值。如果得到的值是 NaN,則減法的結(jié)果就是 NaN。如果對象沒有 valueOf() 方法,則調(diào)用其 toString()方法并將得到的字符串轉(zhuǎn)換為數(shù)值。
如果是 null 減 null,則結(jié)果是 0;
如果是 undefined 減 undefined,則結(jié)果是 NaN;
下面來舉幾個(gè)例子:
var result1 = 5 - true; // 4,因?yàn)閠rue被轉(zhuǎn)換成了1 var result2 = NaN - 1; // NaN var result3 = 5 - 3; // 2 var result4 = 5 - ""; // 5,因?yàn)?" 被轉(zhuǎn)換成了0 var result5 = 5 - "2"; // 3,因?yàn)?2"被轉(zhuǎn)換成了2 var result6 = 5 - null; // 5,因?yàn)閚ull被轉(zhuǎn)換成了0等值運(yùn)算符
確定兩個(gè)變量是否相等是編程中的一個(gè)非常重要的操作。在比較簡單數(shù)據(jù)類型之間的相等性時(shí),問題還比較簡單。但在涉及到對象之間的比較時(shí),問題就變得復(fù)雜了。最早的 JavaScript 中的相等和不等運(yùn)算符會在執(zhí)行比較之前,先將對象轉(zhuǎn)換成相似的類型。后來,有人提出了這種轉(zhuǎn)換到底是否合理的質(zhì)疑。最后,JavaScript 的解決方案就是提供兩組運(yùn)算符:相等和不相等(先轉(zhuǎn)換再比較),恒等和不恒等(僅比較而不轉(zhuǎn)換)。
== != 運(yùn)算符== != 這兩個(gè)運(yùn)算符都會先轉(zhuǎn)換操作數(shù)(通常稱為強(qiáng)制轉(zhuǎn)型),然后再比較它們的相等性。在轉(zhuǎn)換不同的數(shù)據(jù)類型時(shí),相等和不相等運(yùn)算符遵循下列基本規(guī)則:
如果有一個(gè)操作數(shù)是布爾值,則在比較相等性之前先將其轉(zhuǎn)換為數(shù)值(false 轉(zhuǎn)換為 0,而 true 轉(zhuǎn)換為 1);
如果一個(gè)操作數(shù)是字符串,另一個(gè)操作數(shù)是數(shù)值,在比較相等性之前先將字符串轉(zhuǎn)換為數(shù)值;
如果一個(gè)操作數(shù)是對象,另一個(gè)操作數(shù)不是,則調(diào)用對象的 valueOf() 方法,用得到的基本類型值按照前面的規(guī)則進(jìn)行比較;
null 和 undefined 是相等的。
要比較相等性之前,不能將 null 和 undefined 轉(zhuǎn)換成其他任何值。
如果有一個(gè)操作數(shù)是 NaN,則相等運(yùn)算符返回 false,而不相等運(yùn)算符返回 true。重要提示:即使兩個(gè)操作數(shù)都是 NaN,相等運(yùn)算符也返回 false;因?yàn)榘凑找?guī)則,NaN 不等于 NaN。
如果兩個(gè)操作數(shù)都是對象,則比較它們是不是同一個(gè)對象。如果兩個(gè)操作數(shù)都指向同一個(gè)對象,則相等運(yùn)算符返回 true;否則,返回 false。
列出了一些特殊情況及比較結(jié)果:
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=== !== 運(yùn)算符
除了在比較之前不轉(zhuǎn)換操作數(shù)之外,恒等和不恒等運(yùn)算符與相等和不相等運(yùn)算符沒有什么區(qū)別。它只在兩個(gè)操作數(shù)未經(jīng)轉(zhuǎn)換就相等的情況下返回 true,如下面的例子所示:
var result1 = ("55" == 55); // true,因?yàn)檗D(zhuǎn)換后相等 var result2 = ("55" === 55); // false,因?yàn)椴煌臄?shù)據(jù)類型不相等 var result3 = (null == undefined) // true,因?yàn)樗鼈兪穷愃频闹?var result4 = (null === undefined) // false,因?yàn)樗鼈兪遣煌愋偷闹?/pre> 關(guān)系運(yùn)算符 < > <= >= 運(yùn)算符< 小于、> 大于、<= 小于等于、 >= 大于等于 這幾個(gè)關(guān)系運(yùn)算符用于對兩個(gè)值進(jìn)行比較返回一個(gè)布爾值。與 JavaScript 中的其他運(yùn)算符一樣,當(dāng)關(guān)系運(yùn)算符的操作數(shù)使用了非數(shù)值時(shí),也要進(jìn)行數(shù)據(jù)轉(zhuǎn)換或完成某些奇怪的操作。以下就是相應(yīng)的規(guī)則。
如果兩個(gè)操作數(shù)都是數(shù)值,則執(zhí)行數(shù)值比較。
如果兩個(gè)操作數(shù)都是字符串,則比較兩個(gè)字符串對應(yīng)的字符編碼值(可以通過字符串的 charCodeAt() 函數(shù)獲取字符編碼值)。
如果一個(gè)操作數(shù)是數(shù)值,則將另一個(gè)操作數(shù)轉(zhuǎn)換為一個(gè)數(shù)值,然后執(zhí)行數(shù)值比較。
如果一個(gè)操作數(shù)是對象,則調(diào)用這個(gè)對象的 valueOf() 方法,用得到的結(jié)果按照前面的規(guī)則執(zhí)行比較。如果對象沒有 valueOf()方法,則調(diào)用 toString()方法,并用得到的結(jié)果根據(jù)前面的規(guī)則執(zhí)行比較。
如果一個(gè)操作數(shù)是布爾值,則先將其轉(zhuǎn)換為數(shù)值,然后再執(zhí)行比較。
請思考下面幾個(gè)例子的結(jié)果是如何得出的:
var result1 = "Brick" < "alphabet"; // true var result2 = "brick" < "alphabet"; // false var result3 = "23" < "3"; // true var result4 = "23" < 3; // false var result5 = "a" < 3; // false var result6 = NaN < 3; // false var result7 = NaN >= 3; // falsein 運(yùn)算符in 運(yùn)算符希望它的左操作數(shù)是一個(gè)字符串或可以轉(zhuǎn)換為字符串,希望它的右操作數(shù)是一個(gè)對象。如果右側(cè)的對象擁有一個(gè)名為左操作數(shù)值的屬性名,那么表達(dá)式返回 true,例如:
var point = { x:1, y:1 }; // 定義一個(gè)對象 "x" in point // true,對象有一個(gè)名為"x"的屬性 "z" in point // false,對象中不存在名為"z"的屬性 "toString" in point // true,對象繼承了toString()方法 var data = [7,8,9]; // 擁有三個(gè)元素的數(shù)組 "0" in data // true,數(shù)組包含元素"0" 1 in data // true,數(shù)字轉(zhuǎn)換為字符串 3 in data // false,沒有索引為3的元素instanceof 運(yùn)算符instanceof 運(yùn)算符希望左操作數(shù)是一個(gè)對象,右操作數(shù)標(biāo)識對象的類。如果左側(cè)的對象是右側(cè)類的實(shí)例,則表達(dá)式返回 true;否則返回 false。后面會講 JavaScript 中對象的類是通過初始化它們的構(gòu)造函數(shù)來定義的。這樣的話,instanceof 的右操作數(shù)應(yīng)當(dāng)是一個(gè)函數(shù)。比如:
var d = new Date(); // 通過 Date() 構(gòu)造函數(shù)來創(chuàng)建一個(gè)新對象 d instanceof Date; // true,d 是由 Date() 創(chuàng)建的 d instanceof Object; // true,所有的對象都是 Object 的實(shí)例 d instanceof Number; // false,d 不是一個(gè) Number 對象 var a = [1, 2, 3]; // 通過數(shù)組字面量的寫法創(chuàng)建一個(gè)數(shù)組 a instanceof Array; // true,a 是一個(gè)數(shù)組 a instanceof Object; // true,所有的數(shù)組都是對象 a instanceof RegExp; // false,數(shù)組不是正則表達(dá)式需要注意的是,所有的對象都是 Object 的實(shí)例。當(dāng)通過 instanceof 判斷一個(gè)對象是否是一個(gè)類的實(shí)例的時(shí)候,這個(gè)判斷也會包含對「父類」的檢測。如果 instanceof 的左操作數(shù)不是對象的話,instanceof 返回 false。如果右操作數(shù)不是函數(shù),則拋出一個(gè)類型錯(cuò)誤異常。
邏輯運(yùn)算符邏輯運(yùn)算符是對操作數(shù)進(jìn)行布爾算術(shù)運(yùn)算,經(jīng)常和關(guān)系運(yùn)算符一起配合使用,邏輯運(yùn)算符將多個(gè)關(guān)系表達(dá)式組合起來組成一個(gè)更復(fù)雜的表達(dá)式。
&& 邏輯與邏輯與操作可以應(yīng)用于任何類型的操作數(shù),而不僅僅是布爾值。在有一個(gè)操作數(shù)不是布爾值的情況下,邏輯與操作不一定返回布爾值;此時(shí),它遵循下列規(guī)則:
如果第一個(gè)操作數(shù)是對象,則返回第二個(gè)操作數(shù);
如果第二個(gè)操作數(shù)是對象,則只有在第一個(gè)操作數(shù)的求值結(jié)果為 true 的情況下才會返回該對象;
如果兩個(gè)操作數(shù)都是對象,則返回第二個(gè)操作數(shù);
如果有一個(gè)操作數(shù)是 null,則返回 null;
如果有一個(gè)操作數(shù)是 NaN,則返回 NaN;
如果有一個(gè)操作數(shù)是 undefined,則返回 undefined。
邏輯與操作屬于短路操作,即如果第一個(gè)操作數(shù)能夠決定結(jié)果,那么就不會再對第二個(gè)操作數(shù)求值。對于邏輯與操作而言,如果第一個(gè)操作數(shù)是 false,無論第二個(gè)操作數(shù)是什么值,結(jié)果都不再可能是 true 了。
|| 邏輯或與邏輯與操作相似,如果有一個(gè)操作數(shù)不是布爾值,邏輯或也不一定返回布爾值;此時(shí),它遵循下列規(guī)則:
如果第一個(gè)操作數(shù)是對象,則返回第一個(gè)操作數(shù);
如果第一個(gè)操作數(shù)的求值結(jié)果為 false,則返回第二個(gè)操作數(shù);
如果兩個(gè)操作數(shù)都是對象,則返回第一個(gè)操作數(shù);
如果兩個(gè)操作數(shù)都是 null,則返回 null;
如果兩個(gè)操作數(shù)都是 NaN,則返回 NaN;
如果兩個(gè)操作數(shù)都是 undefined,則返回 undefined。
與邏輯與運(yùn)算符相似,邏輯或運(yùn)算符也是短路運(yùn)算符。也就是說,如果第一個(gè)操作數(shù)的求值結(jié)果為 true,就不會對第二個(gè)操作數(shù)求值了。
! 邏輯非邏輯非操作可以應(yīng)用于任何類型的操作數(shù),無論這個(gè)值是什么數(shù)據(jù)類型,這個(gè)運(yùn)算符都會返回一個(gè)布爾值。邏輯非運(yùn)算符首先會將它的操作數(shù)轉(zhuǎn)換為一個(gè)布爾值,然后再對其求反。邏輯非運(yùn)算符遵循下列規(guī)則:
如果操作數(shù)是一個(gè)對象,返回 false;
如果操作數(shù)是一個(gè)空字符串,返回 true;
如果操作數(shù)是一個(gè)非空字符串,返回 false;
如果操作數(shù)是數(shù)值 0,返回 true;
如果操作數(shù)是任意非 0 數(shù)值(包括 Infinity),返回 false;
如果操作數(shù)是 null,返回 true;
如果操作數(shù)是 NaN,返回 true;
如果操作數(shù)是 undefined,返回 true。
下面幾個(gè)例子展示了應(yīng)用上述規(guī)則的結(jié)果:
console.log(!false); // true console.log(!"blue"); // false console.log(!0); // true console.log(!NaN); // true console.log(!""); // true console.log(!12345); // false邏輯非運(yùn)算符也可以用于將一個(gè)值轉(zhuǎn)換為與其對應(yīng)的布爾值。而同時(shí)使用兩個(gè)邏輯非運(yùn)算符,實(shí)際上就會模擬 Boolean() 轉(zhuǎn)型函數(shù)的行為。其中,第一個(gè)邏輯非操作會基于無論什么操作數(shù)返回一個(gè)布爾值,而第二個(gè)邏輯非操作則對該布爾值求反,于是就得到了這個(gè)值真正對應(yīng)的布爾值。當(dāng)然,最終結(jié)果與對這個(gè)值使用 Boolean() 函數(shù)相同,例如:
console.log(!!"blue"); //true console.log(!!0); //false console.log(!!NaN); //false console.log(!!""); //false console.log(!!12345); //true位運(yùn)算符在 JavaScript 中,當(dāng)對數(shù)值應(yīng)用位運(yùn)算符時(shí),后臺會發(fā)生如下轉(zhuǎn)換過程:64位的數(shù)值被轉(zhuǎn)換成32位數(shù)值,然后執(zhí)行位操作,最后再將32位的結(jié)果轉(zhuǎn)換回64位數(shù)值。這個(gè)轉(zhuǎn)換過程導(dǎo)致了一個(gè)嚴(yán)重的副效應(yīng),即在對特殊的 NaN 和 Infinity 值應(yīng)用位操作時(shí),這兩個(gè)值都會被當(dāng)成 0 來處理。如果對非數(shù)值應(yīng)用位運(yùn)算符,會先使用 Number() 函數(shù)將該值轉(zhuǎn)換為一個(gè)數(shù)值,然后再應(yīng)用位操作,得到的結(jié)果將是一個(gè)數(shù)值。
~ 按位非簡單的理解,對任一數(shù)值 x 進(jìn)行按位非操作的結(jié)果為 -(x+1)。例如:
console.log(~null); // -1 console.log(~undefined); // -1 console.log(~0); // -1 console.log(~{}); // -1 console.log(~[]); // -1 console.log(~(1/0)); // -1 console.log(~false); // -1 console.log(~true); // -2 console.log(~1.2543); // -2 console.log(~4.9); // -5 console.log(~(-2.999)); // 1& 按位與按位與操作就是將兩個(gè)數(shù)值的每一位對齊,兩個(gè)數(shù)值的對應(yīng)位都是 1 時(shí)才返回 1,任何一位是 0,結(jié)果都是 0。如下表所示:
第一個(gè)數(shù)值的位 | 第二個(gè)數(shù)值的位 | 結(jié)果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
按位或操作就是將兩個(gè)數(shù)值的每一位對齊,兩個(gè)數(shù)值只要有一個(gè)位是 1 就返回 1,只在兩個(gè)位都是 0 的情況下才返回 0。如下表所示:
第一個(gè)數(shù)值的位 | 第二個(gè)數(shù)值的位 | 結(jié)果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
按位異或與按位或的不同之處在于,兩個(gè)數(shù)值只有一個(gè) 1 時(shí)才返回 1,如果對應(yīng)的兩位都是 1 或都是 0,則返回 0。
第一個(gè)數(shù)值的位 | 第二個(gè)數(shù)值的位 | 結(jié)果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
這個(gè)運(yùn)算符會將數(shù)值的所有位向左移動指定的位數(shù)。例如:
var oldValue = 2; // 等于二進(jìn)制的 10 var newValue = oldValue << 5; // 等于二進(jìn)制的 1000000,十進(jìn)制的 64
注意,左移不會影響操作數(shù)的符號位。換句話說,如果將 -2 向左移動 5 位,結(jié)果將是 -64,而非 64。
>> 有符號的右移這個(gè)運(yùn)算符會將數(shù)值向右移動,但保留符號位(即正負(fù)號標(biāo)記)。
var oldValue = 64; // 等于二進(jìn)制的 1000000 var newValue = oldValue >> 5; // 等于二進(jìn)制的 10 ,即十進(jìn)制的 2>>> 無符號的右移
這個(gè)運(yùn)算符會將數(shù)值的所有32位都向右移動。對正數(shù)來說,無符號右移的結(jié)果與有符號右移相同。
var oldValue = 64; // 等于二進(jìn)制的 1000000 var newValue = oldValue >>> 5; // 等于二進(jìn)制的 10 ,即十進(jìn)制的 2
無符號右移運(yùn)算符會把負(fù)數(shù)的二進(jìn)制碼當(dāng)成正數(shù)的二進(jìn)制碼。而且,由于負(fù)數(shù)以其絕對值的二進(jìn)制補(bǔ)碼形式表示,因此就會導(dǎo)致無符號右移后的結(jié)果非常之大。
var oldValue = -64; // 等于二進(jìn)制的 11111111111111111111111111000000 var newValue = oldValue >>> 5; // 等于十進(jìn)制的 134217726賦值運(yùn)算符
簡單的賦值運(yùn)算符由等于號 = 表示,其作用就是把右側(cè)的值賦給左側(cè)的變量,如下面的例子所示:
var num = 10;
如果在等于號 = 前面再添加乘性運(yùn)算符、加性運(yùn)算符或位運(yùn)算符,就可以完成復(fù)合賦值操作。這種復(fù)合賦值操作相當(dāng)于是對下面常規(guī)表達(dá)式的簡寫形式:
var num = 10; num += 10; // 等同于 num = num + 10;
每個(gè)主要算術(shù)運(yùn)算符(以及個(gè)別的其他運(yùn)算符)都有對應(yīng)的復(fù)合賦值運(yùn)算符。這些運(yùn)算符如下所示:
乘/賦值 *=;
除/賦值 /=;
模/賦值 %=;
加/賦值 +=;
減/賦值 -=;
左移/賦值 <<=;
有符號右移/賦值 >>=;
無符號右移/賦值 >>>=。
設(shè)計(jì)這些運(yùn)算符的主要目的就是簡化賦值操作,使用它們不會帶來任何性能的提升。
條件運(yùn)算符? : 條件運(yùn)算符應(yīng)該算是 JavaScript 中最靈活的一種運(yùn)算符了,而且它遵循與 Java 中的條件運(yùn)算符相同的語法形式,如下面的例子所示:
variable = boolean_expression ? true_value : false_value;逗號運(yùn)算符
逗號運(yùn)算符多用于聲明多個(gè)變量;但除此之外,逗號運(yùn)算符還可以用于賦值。在用于賦值時(shí),逗號運(yùn)算符總會返回表達(dá)式中的最后一項(xiàng),如下面的例子所示:
var num = (5, 1, 4, 8, 0); // num 的值為 0
由于 0 是表達(dá)式中的最后一項(xiàng),因此 num 的值就是 0。雖然逗號的這種使用方式并不常見,但這個(gè)例子可以幫我們理解逗號的這種行為。
關(guān)卡// 挑戰(zhàn)一 var x=1; if(!!function f(){}){ x+=typeof f; } console.log(x); // ???
// 挑戰(zhàn)二 (function f(f){ console.log(typeof f()); // ??? })(function(){return 1;});
// 挑戰(zhàn)三 console.log(typeof 2*3); // ??? console.log(typeof 2+3); // ???
// 挑戰(zhàn)四 var a=0,b=0; console.log(a+++b); // ??? console.log(a); // ??? console.log(b); // ???
// 挑戰(zhàn)五 var a,b,c; a=b==c; console.log(a); // ???
// 挑戰(zhàn)六 console.log(1 && 3); // ??? console.log(1 && "foo" || 0); // ??? console.log(1 || "foo" && 0); // ???
// 挑戰(zhàn)七 var a=1; var b=(a=(2,4,6))+a++ console.log(b); // ???
// 挑戰(zhàn)八 if (!("a" in window)) { var a = 1; } console.log(a); // ???
// 挑戰(zhàn)九 var val = "smtg"; console.log("Value is " + (val === "smtg") ? "Something" : "Nothing"); // ???
// 挑戰(zhàn)九 console.log(1 + - + + + - + 1);更多
關(guān)注微信公眾號「劼哥舍」回復(fù)「答案」,獲取關(guān)卡詳解。
關(guān)注 https://github.com/stone0090/javascript-lessons,獲取最新動態(tài)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80144.html
摘要:對象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對象模型是針對和文檔的一個(gè)。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動態(tài)的,根闖關(guān)記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...
摘要:本課程之所以叫做闖關(guān)記,是因?yàn)椴糠终鹿?jié)精心設(shè)計(jì)了挑戰(zhàn)關(guān)卡,通過提供更多的實(shí)戰(zhàn)機(jī)會,讓大家可以循序漸進(jìn)地有目的地有挑戰(zhàn)地開展學(xué)習(xí)。課程結(jié)構(gòu)及目錄以下目錄只是初步構(gòu)想,課程結(jié)構(gòu)及內(nèi)容會根據(jù)實(shí)際情況隨時(shí)進(jìn)行調(diào)整。 為何寫作此課程 stone 主要負(fù)責(zé)基于 Web 的企業(yè)內(nèi)部管理系統(tǒng)的開發(fā),雖然能夠熟練地使用 JavaScript,但隨著對 JavaScript 的理解越來越深,才發(fā)現(xiàn)自己尚...
摘要:屬性名可以是包含空字符串在內(nèi)的任意字符串,但對象中不能存在兩個(gè)同名的屬性??蛻舳酥斜硎揪W(wǎng)頁結(jié)構(gòu)的對象均是宿主對象。這里的函數(shù)稱做構(gòu)造函數(shù),構(gòu)造函數(shù)用以初始化一個(gè)新創(chuàng)建的對象。通過關(guān)鍵字和構(gòu)造函數(shù)調(diào)用創(chuàng)建的對象的原型就是構(gòu)造函數(shù)的屬性的值。 對象是 JavaScript 的數(shù)據(jù)類型。它將很多值(原始值或者其他對象)聚合在一起,可通過名字訪問這些值,因此我們可以把它看成是從字符串到值的映射...
摘要:瀏覽器只是實(shí)現(xiàn)的宿主環(huán)境之一,其他宿主環(huán)境包括和。年月,版發(fā)布,成為國際標(biāo)準(zhǔn)。事件定義了事件和事件處理的接口。對于已經(jīng)正式納入標(biāo)準(zhǔn)的來說,盡管各瀏覽器都實(shí)現(xiàn)了某些眾所周知的共同特性,但其他特性還是會因?yàn)g覽器而異。 JavaScript 是面向 Web 的編程語言,絕大多數(shù)現(xiàn)代網(wǎng)站都使用了 JavaScript,并且所有的現(xiàn)代 Web 瀏覽器(電腦,手機(jī),平板)均包含了 JavaScri...
摘要:把上面的函數(shù)聲明改為等價(jià)的函數(shù)表達(dá)式,就會在執(zhí)行期間導(dǎo)致錯(cuò)誤。換句話說,引用的是函數(shù)據(jù)以執(zhí)行的環(huán)境對象當(dāng)在網(wǎng)頁的全局作用域中調(diào)用函數(shù)時(shí),對象引用的就是。這兩個(gè)方法的用途都是在特定的作用域中調(diào)用函數(shù),實(shí)際上等于設(shè)置函數(shù)體內(nèi)對象的值。 函數(shù)是一段代碼,它只定義一次,但可以被執(zhí)行或調(diào)用任意次。在 JavaScript 里,函數(shù)即對象,程序可以隨意操控它們。比如,可以把函數(shù)賦值給變量,或者作為...
閱讀 1119·2021-11-23 09:51
閱讀 1086·2021-10-18 13:31
閱讀 2999·2021-09-22 16:06
閱讀 4291·2021-09-10 11:19
閱讀 2209·2019-08-29 17:04
閱讀 439·2019-08-29 10:55
閱讀 2489·2019-08-26 16:37
閱讀 3384·2019-08-26 13:29