Javascript基礎之-強制類型轉換(三)

這一節,應該算是強制類型轉換的最後一個小節了,這一部分呢,主要會講比較操做中遇到的強制類型轉換。數組

抽象相等(==)和嚴格相等(===)。函數

簡單且粗略的來講,抽象相等和嚴格相等的區別就是抽象相等在比較的時候,若是比較的兩個數類型不一樣,會先進行類型轉換再比較,而嚴格類型呢,比較簡單粗暴一些,直接返回false。prototype

固然啦,你也能夠這麼理解,抽象比較的時候,容許類型轉換,而嚴格相等則不容許,因此看以下例子:code

console.log('1111' == 1111)   // true
console.log('1111' === 1111)  // false

這個例子很容易理解,那麼本例中,抽象相等中到底是從字符串轉換爲數字呢,仍是相反?對象

規範是這麼說的:ip

若是相比較的兩個操做數,其中一個是數字類型,另外一個是字符串類型的話,那麼字符串將會轉換爲數字,再進行比較,就相等於:文檔

console.log(Number('1111') == 1111);

那麼若是是布爾值呢?好比說字符串

console.log("42" == true);  // false
console.log(12 == true);  // false
console.log(-1 == true);   // false

哇哦,都是false呀,是否是和一開始的認知不太同樣呢?尤爲是對於有其餘語言基礎的童鞋們。get

這一方面ecma規範也有說了:it

若是操做數中,有布爾類型的,那麼他將會轉爲數字類型,再進行比較。

你們請看着個例子,應該不用多說了吧,上面說過了,嚴格相等的話,若是類型不同,直接返回false,畢竟人家是嚴格相等,很嚴格的。

console.log(false === 0); // false
console.log(false == 0); // true

那麼若是null和undefined比較呢?

console.log(null == null); // true
console.log(undefined == null); // true
console.log(undefined == undefined) // true

第一個和第三個你們比較容易理解,第二個可能比較疑惑,爲甚呢?

由於規範上有說,若是比較的兩種,一個是undefined另外一種是null,則返回true,可是這個也只是對應於抽象相等,嚴格相等時不可能相等的。由於類型不同。

至於上面那個呢,我還應該多說一句,除了undefined和null比較或者是他們同類型的比較是true,和其餘任何類型的值比較都是false,有一些看起來像true的,結果都是false,要注意一下。

console.log(null == false); // false
console.log(undefined == 0); // false
console.log(undefined == "") // false

接下來這個比較重要了,就是對象和非對象的比較。

先看規範定義吧:

對於兩個操做數,若是其中一個是字符串或數字,另外一個是對象的話,那麼對象會轉爲原始值,而後再進行比較。

那麼怎麼獲取原始值呢?

其實其餘小節也都講過,這裏在複述一下,簡單來講,就是先調用對象的valueOf()函數,若是它不存在,或者不會轉爲基本類型值,就調用toString()函數,若是toString()不存在或者返回的是非字符串的值,將會直接報錯。

看起來有一點枯燥吧,那麼看例子。

console.log([2].valueOf());  // [2]
console.log([2].toString());  // "2"
console.log([2].toString() == 2);  // true

數組[2]呢,能夠看到,他的valueOf返回的是一個數組,那麼他就會用toString(),轉爲字符串「2」,字符串2和數字2比較呢,根據上面講的,字符串2會變爲數字2,相等,返回true。

在看一個例子

var obj = {
  valueOf() {
    return 3;
  }
}
console.log(obj == 3);  // true
var obj1 = Object.create(null);
console.log(obj1 == 3);  // Uncaught TypeError: Cannot convert object to primitive value

這個呢,就是對象先調用valueOf()獲得基本類型值3,而後再進行比較獲得true,第二個呢,獲得了一個純淨的對象(沒有prototype),而後獲取不到valueOf()和toString(),直接報錯了。

那其餘的狀況呢

console.log(NaN == NaN);  // false
console.log(NaN === NaN);  // false
console.log(+0 == -0);   // true
console.log(+0 === -0);  // true
console.log({} == {});  // false
console.log({} === {});  // false
var obj1 = obj = {};
console.log(obj == obj1);  // true
console.log(obj === obj1);  // true

這個分析一下,規範中:

NaN不等於自身,+0和-0是相等的,對象是否相等是根據是否引用同一對象。

對象相等的已經介紹完了,那麼判斷不相等的呢?好比說(!=)和(!==)他們的區別呢

實際上,他們的語法判斷規則和相等的規則同樣,只不過最後多了一個置反的一個步驟。也就是!(a == b)或者是!(a === b),我感受應該很容易理解,就不舉例了。

那麼最後就要講關係操做符了,也就是大於小於這些的。

那麼咱們先講兩個操做符中,有至少是一個數字的狀況。請看下面的例子

console.log(1 < 2);  // true
console.log("0b1" < 2);  // true
var obj = {
  valueOf() {
    return 1;
  }
}
console.log(obj < 2);   // true
console.log(1 < Infinity);  // true
console.log(-Infinity < 1);  // true
console.log(NaN > 1);  // false
console.log(NaN < 1);  // false

上面這幾個例子,幾乎涵蓋了規範中至少有一個操做數是數字的比較的狀況。

首先,也是若是有對象的話,會把對象轉爲基本類型值,在進行比較。

而且若是另外一個操做數是字符串的話,會把字符串轉成數字。

還有就是數字一直小於正無窮,大於負無窮。

NaN不管怎麼判斷都是false。

那麼若是是字符串之間的比較呢,也就是倆操做數都是字符串的狀況。

console.log("1003" > "2");  // false

嗯,很簡單是吧,若是倆都是字符串的話,實際上會按照字母順序去比,這樣去排出哪一個值。

那麼是怎麼按照字母順序比的呢,字母順序又是經過什麼方式取得的呢?請看例子:

console.log("aaa" > "aa"); // true
console.log("1003" > "2");  // false
console.log("a" > "b");  // false
console.log('&' < "a");  // true
console.log("A" < "a");  // true
console.log("a".charCodeAt());  // 97
console.log("b".charCodeAt());  // 98
console.log("&".charCodeAt());  // 38
console.log("A".charCodeAt());  // 65

這個例子,應該就很容易理解了,實際上取的是字符串的charCodeAt(),實際上你依然能夠理解爲轉換成數字去比了,只不過字符串的比和含有數字的比是不同的,數字的比意味着他們總體數字的值的大小去比,而字符串是比從一開始的前綴挨個比每一個字母的大小。

是否是依然比較好理解,那麼在來一個例子。

var a = [ 42 ];
var b = "043";
console.log(a < b);  // false
console.log(Number(a) < Number(b)); // true

這個結合上面那個規則,本身分析下。

最後的最後,咱們看一個你可能略感疑惑的例子:

var a = { b: 42 };
var b = { b: 43 };
console.log(a < b);  // false
console.log(a == b); // false
console.log(a > b);  // false
console.log(a <= b);  // true
console.log(a >= b);  // true

這個例子,確實不太付合常識呀,可是呢,這確實是存在的,我給解釋一下。

首先呢,a < b和a > b,因爲他們倆都是對象,因此轉換爲基本類型值後爲字符串「[object Object]」,因此返回false,而a == b呢,則是由於他倆並非同一個對象的不一樣的引用,因此返回false。

最後倆呢,實際上大於等於或者小於等於能夠理解爲大於或者小於的值的反值,也就是: !(a <= b),因此前面爲false,反一下爲true

好啦,三個小章基本把強制類型轉換整個梳理了一遍,由於這一塊的細節太多,因此說呢,我反卻是建議讀到我這裏的小夥伴,先把大致規則瞭解之後,特別細節的規則,用到的時候看看個人小散文,或者直接去看ecma262標準文檔也行,可是呢,強調一點就是,假如真的要用以前,仍是建議本身吧代碼跑一下,這樣個人感觸就是要比只看效果好太多。

總之感謝你們收看個人小散文。

參考書籍《你不知道的Javascript中卷》

參考文檔:ECMAScript 5.1(ECMA-262)

https://www.ecma-internationa...

本文轉載自http://www.lht.ren/article/7/

相關文章
相關標籤/搜索