基本概念
ECMAScript 中有 5 種簡單數據類型(也稱爲基本數據類型,存放在棧中):Undefined、Null、Boolean、Number
和String
。還有 1 種複雜數據類型——Object
(存放在堆內存中)。ES6的Symbol
暫且不論。
簡單粗暴地描述一下這幾個類型:
-
Undefined 類型只有一個值,即特殊的
undefined
。在使用 var 聲明變量但未對其加以初始化時,這個變量的值就是undefined
,例如:var message; alert(message == undefined); //true
- Null 類型是第二個只有一個值的數據類型,這個特殊的值是
null
。從邏輯角度來看,null
值表示一個空對象指針。 - Boolean類型:
true
和false
。 - Number類型:阿拉伯數字的(八進制、十進制、十六進制、整數、浮點數、5e-324 ~ 1.7976931348623157e+308、NaN……)。
-
String類型:帶引號的,單引號雙引號都可以(字符串),還有一些特殊的字符字面量(
\n
之類的)var firstName = "Nicholas"; var lastName = 'Zakas';
-
Object類型:ECMAScript 中的對象其實就是一組數據和功能的集合(萬物皆對象😄)。對象可以通過執行 new 操作符後跟要創建 的對象類型的名稱來創建。而創建 Object 類型的實例併爲其添加屬性和(或)方法,就可以創建自定義對象,如下所示:
var o = new Object();
typeof
操作符
鑑於 ECMAScript 是鬆散類型的,因此需要有一種手段來檢測給定變量的數據類型——typeof就是負責提供這方面信息的操作符。對一個值使用 typeof 操作符可能返回下列某個字符串:
- "undefined"——如果這個值未定義;
- "boolean"——如果這個值是布爾值;
- "string"——如果這個值是字符串;
- "number"——如果這個值是數值;
- "object"——如果這個值是對象或 null;
- "function"——如果這個值是函數。
有一些需要注意的地方:
- 有些時候,typeof 操作符會返回一些令人迷惑但技術上卻正確的值。比如,調用
typeof null
會返回"object"
,因爲特殊值null
被認爲是一個空的對象引用。從邏輯角度來看,null 值表示一個空對象指針,而這也正是使用typeof操作符檢測null值時會返回"object"的原因。 -
首先,任何涉及 NaN 的操作(例如 NaN/10)都會返回 NaN,這個特點在多步計算中有可能導致問題。其次,NaN與任何值都不相等,包括NaN本身。例如,下面的代碼會返回 false:
alert(NaN == NaN); //false
-
另外,NaN實際上是一種特殊的number
typeof NaN "number"
- 《JavaScript高級程序設計》原書上寫道:“任何數值除以0都會返回NaN”,但實際上只有 0 除以 0 纔會返回 NaN,正數除以 0 返回 Infinity,負數除以 0 返回-Infinity。
- ECMAScript定義了isNaN()函數幫我們確定這個參數是否“不是數值”。isNaN()在接收到一個值之後,會嘗試 將這個值轉換爲數值。某些不是數值的值會直接轉換爲數值。下面看幾個例子:
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false(10 是一個數值)
alert(isNaN("10")); //false(可以被轉換成數值 10)
alert(isNaN("blue")); //true(不能轉換成數值)
alert(isNaN(true)); //false(可以被轉換成數值 1)
再來看一張圖:
如果被這個人猥瑣的笑容嚇到了可以先看最下面的《JavaScript高級程序設計》原理部分。
下面對圖上的內容進行分析
> typeof NaN
<· "number"
上面已經提到,在其他編程語言中,任何數值除以 0 都會導致錯誤,從而停止代碼執行。但在 ECMAScript 中,任何數值除以 0 會返回 NaN (原書如此,但實際上只有 0 除以 0 纔會返回 NaN,正數除以 0 返回 Infinity,負數除以 0 返回-Infinity),而其被定義爲number類型。
> 9999999999999999
<· 10000000000000000
> 0.5 + 0.1 == 0.6
<· true
> 0.1 + 0.2 == 0.3
<· false
這個是JavaScript的坑,如果非要究其原因,可以看這篇文章:js中0.1+0.2爲什麼不等於0.3。
PS:在後面的冪大於20的時候會顯示成科學計數法:
> 999999999999999990000
<· 1e+21
上部分的實際結果:
> 0.5 + 0.1
<· 0.6
> 0.1 + 0.2
<· 0.30000000000000004
> Math.max()
<· -Infinity
> Math.min()
<· Infinity
Math.max() 函數返回一組數中的最大值。
如果沒有參數,則結果爲 -Infinity。
如果有任一參數不能被轉換爲數值,則結果爲 NaN。
引用自MDN。
我的理解是沒有參數時,需要比較的一組值就是空,那麼空裏面的最大值就是-Infinity,Math.min()同理(個人理解,如有錯誤請指正)。
> [] + []
<· ""
> [] + {}
<· "[object Object]"
> {} + []
<· 0
> true + true + true === 3
<· true
> true - true
<· 0
> true == 1
<· true
> true === 1
<· false
> (! + [] + [] + ![]).length
<· 9
> 9 + "1"
<· "91"
> 91 - "1"
<· 90
> [] == 0
<· true
這裏的大部分運算結果涉及的類型轉化可以參考《JavaScript高級程序設計》,文末也有摘抄。
> true + true + true === 3
<· true
> true - true
<· 0
> true == 1
<· true
> true === 1
<· false
這幾個運算可能和書上寫的有些偏差,“如果有一個操作數是對象、數值或布爾值,則調用它們的 toString()方法取得相應的字符串值,然後再應用前面關於字符串的規則”,——如果是布爾值加減操作,true轉爲1,false轉爲0。
> true + false
<· 1
再看這個
> [] + {}
<· "[object Object]"
> {} + []
<· 0
[] + {}
可以理解是調用了各自的toString()方法後再應用字符串相加的規則.
> [].toString()
<· ""
> var obj = {}
<· undefined
> obj.toString()
<· "[object Object]"
相加結果得到"[object Object]"
{} + []
爲什麼結果是0?
實際上是控制檯把{}
當做了一個空白表達式,實際上是在計算+ []
。一元加運算符優先把右邊的參數轉化爲number,就得到了0
。如果是上面的obj + []
得到的結果就和[] + {}
一樣都是"[object Object]"
着重看一下這個例子:(! + [] + [] + ![]).length
首先,邏輯非!有着極高的優先級,所以首先計算的是! + []
和![]
。+ []
: + 運算符將[]轉化爲number結果爲0,![]
結果爲false
。
式子變成了(true + [] + false).length
[].toString()
爲"",true + ""
爲"true"
,"true" + false
爲"truefalse"
."truefalse"
長度爲9。
《JavaScript高級程序設計》:
加性操作符
加法 加法操作符(+)的用法如下所示:
var result = 1 + 2;
- 如果兩個操作符都是數值,執行常規的加法計算,然後根據下列規則返回結果:
- 如果有一個操作數是 NaN,則結果是 NaN;
- 如果是Infinity 加 Infinity,則結果是 Infinity;
- 如果是-Infinity加-Infinity,則結果是-Infinity;
- 如果是 Infinity 加-Infinity,則結果是 NaN;
- 如果是+0加+0,則結果是+0;
- 如果是+0加-0,則結果是+0。
不過,如果有一個操作數是字符串,那麼就要應用如下規則: - 如果兩個操作數都是字符串,則將第二個操作數與第一個操作數拼接起來;
- 如果只有一個操作數是字符串,則將另一個操作數轉換爲字符串,然後再將兩個字符串拼接起來。
如果有一個操作數是對象、數值或布爾值,則調用它們的 toString()方法取得相應的字符串值,
然後再應用前面關於字符串的規則。對於 undefined 和 null,則分別調用 String()函數並取得字 符 串"undefined"和"null"。
減法 減法操作符(-)是另一個極爲常用的操作符,其用法如下所示:
var result = 2 - 1;
與加法操作符類似,ECMAScript 中的減法操作符在處理各種數據類型轉換時,同樣需要遵循一些特殊規則,如下所示:
- 如果兩個操作符都是數值,則執行常規的算術減法操作並返回結果;
- 如果有一個操作數是 NaN,則結果是 NaN;
- 如果是 Infinity 減 Infinity,則結果是 NaN;
- 如果是-Infinity 減-Infinity,則結果是 NaN;
- 如果是 Infinity 減-Infinity,則結果是 Infinity;
- 如果是-Infinity 減 Infinity,則結果是-Infinity;
- 如果是+0 減+0,則結果是+0;
- 如果是+0 減-0,則結果是-0;
- 如果是-0 減-0,則結果是+0;
- 如果有一個操作數是字符串、布爾值、null 或 undefined,則先在後臺調用 Number()函數將其轉換爲數值,然後再根據前面的規則執行減法計算。如果轉換的結果是 NaN,則減法的結果就是 NaN;
- 如果有一個操作數是對象,則調用對象的 valueOf()方法以取得表示該對象的數值。如果得到的值是 NaN,則減法的結果就是 NaN。如果對象沒有 valueOf()方法,則調用其 toString()方法並將得到的字符串轉換爲數值。
相等和不相等
ECMAScript 中的相等操作符由兩個等於號(==)表示,如果兩個操作數相等,則返回 true。而不相等操作符由歎號後跟等於號(!=)表示,如果兩個操作數不相等,則返回 true。這兩個操作符都會先轉換操作數(通常稱爲強制轉型),然後再比較它們的相等性。
在轉換不同的數據類型時,相等和不相等操作符遵循下列基本規則:
- 如果有一個操作數是布爾值,則在比較相等性之前先將其轉換爲數值——false 轉換爲 0,而true 轉換爲 1;
- 如果一個操作數是字符串,另一個操作數是數值,在比較相等性之前先將字符串轉換爲數值;
- 如果一個操作數是對象,另一個操作數不是,則調用對象的 valueOf()方法,用得到的基本類型值按照前面的規則進行比較;
這兩個操作符在進行比較時則要遵循下列規則:
- null 和 undefined 是相等的。
- 要比較相等性之前,不能將 null 和 undefined 轉換成其他任何值。
PS:簡要帶幾句undefined和null的區別,想要深入理解可以自行查詢,這類文章也挺多的。
null 和 undefined 都表示“值的空缺”,你可以認爲undefined是表示系統級的、出乎意料的或類似錯誤的值的空缺,而null是表示程序級的、正常的或在意料之中的值的空缺。可以認爲undefined表示本該有卻沒有,null是本來就沒有。undefined是未初始化的變量,null是一個空指針對象。佛語有云:“色即是空,空即是色”,“色”想要有卻沒有,“空”本就是空,指針爲空,對象爲空。然而“色即是空,空即是色”,undefined == null也成立,不是風動,不是幡動,忍者心動。
- 如果有一個操作數是 NaN,則相等操作符返回 false,而不相等操作符返回 true。重要提示:即使兩個操作數都是 NaN,相等操作符也返回 false;因爲按照規則,NaN 不等於 NaN。
- 如果兩個操作數都是對象,則比較它們是不是同一個對象。如果兩個操作數都指向同一個對象,則相等操作符返回 true;否則,返回 false。
- 下表列出了一些特殊情況及比較結果:
參考:
- 《JavaScript高級程序設計》
- JavaScript 神奇之旅
在下才疏學淺,如發現錯誤,請批評指正!