首頁  >  文章  >  web前端  >  來探討下JS類型轉換的哪些坑

來探討下JS類型轉換的哪些坑

阿神
阿神原創
2017-01-23 14:18:041176瀏覽

為啥要說這個東西?
一道面試題給我去說它的動機。
題如下:

var bool = new Boolean(false);
if (bool) {
    alert('true');
} else {
    alert('false');
}

運行結果是true! ! !
其實啥型別轉換啊,操作符優先權啊,這些東西都是最基本的。
犀牛書上有詳細的介紹。但我很少去翻犀牛書的前5章。 。 。
比如說優先級那塊兒,很多書都教育我們,「不用去背誦優先順序,不確定的話,加括號就行了。」
平常我們寫程式時也確實這麼做的。
但現實是啥呢?面試時會出這種題,讓你來做。 。 。
真不知道這種題的意義是啥。 。 。
抱怨到此為止,本文嘗試來解決類型轉換問題,爭取把《JS權威指南》49頁那個表背下來。
都有哪些東西是假值?
共6個:

0或+0、-0,NaN
""
false
undefined
null

上面的順序是按照基本類型來排列的。
除此之外的一律不是! !就算是如下形式:

Infinity
'0'、'false'、" "(空格字符)
任何引用类型:[],{},function(){}

if (a && b)的正確理解方式是:a && b進行表達式求值後,然後再轉換為Boolean型別。
&&是種短路語法,求值後不一定是Boolean類型,更不是兩邊轉換布林值再運算。
例如 2&&3 的結果是3,不是true。
所以if(a && b),我們平常理解的那種,"如果a和b同時為真的話",是一種錯誤的描述方式。
其他基本類型轉換為字串,基本上和預期的一樣:

console.log("" + null);      // "null"
console.log("" + undefined); // "undefined"
console.log("" + false);     // "false"
console.log("" + true);      // "true"
console.log("" + 0);         // "0"
console.log("" + NaN);       // "NaN"
console.log("" + Infinity);  // "Infinity"

其他基本類型轉化為數字,需要特殊記憶:

console.log(+null);          // 0
console.log(+undefined);     // NaN
console.log(+false);         // 0
console.log(+true);          // 1
console.log(+"");            // 0
console.log(+'1');           // 1
console.log(+'1x');          // NaN

其中null,空字符是0,undefined是NaN。
以上,基本型別轉換都說明白了。

下面來看看引用型別轉換為基本型別。
引用類型轉換為布爾,始終為true
引用類型轉換為字串

1.优先调用toString方法(如果有),看其返回结果是否是原始类型,如果是,转化为字符串,返回。
2.否则,调用valueOf方法(如果有),看其返回结果是否是原始类型,如果是,转化为字符串,返回。
3.其他报错。

引用類型轉換為數字

1.优先调用valueOf方法(如果有),看其返回结果是否是基本类型,如果是,转化为数字,返回。
2.否则,调用toString方法(如果有),看其返回结果是否是基本类型,如果是,转化为数字,返回。
3.其他报错。

首先我們看看常見引用類型返回什麼?

var a = {};
console.dir(a.toString());   // "[object Object]"
console.dir(a.valueOf());    // 对象本身
 
var b = [1, 2, 3];
console.dir(b.toString());   // "1,2,3"
console.dir(b.valueOf());    // 对象本身
 
var c = [[1],[2]];
console.dir(c.toString());   // "1,2"
console.dir(c.valueOf());    // 对象本身
 
var d = function() {return 2};
console.dir(d.toString());   // "function() {return 2}"
console.dir(d.valueOf());    // 对象本身

因此對應的轉換為字串和數字的情形是:

var a = {};
console.dir(a + "");         // "[object Object]"
console.dir(+a);             // NaN
 
var b = [1, 2, 3];
console.dir(b + "");         // "1,2,3"
console.dir(+b);             // NaN
 
var c = [[1],[2]];
console.dir(c + "");         // "1,2"
console.dir(+c);             // NaN
 
var d = function() {return 2};
console.dir(d + "");         // "function () {return 2}"
console.dir(+d);             // NaN

再來個報錯的情形:

var a = {};
a.toString = function() {return {};}
console.log("" + a);         // 报错
console.log(+a)              // 报错

以上型別轉換規律基本上說完。

最後來說一下萬惡的「==」
面試題如下:

var a = false;
var b = undefined;
if (a == b) {
    alert('true');
} else {
    alert('false');
}

本以為會彈出true的。天那!為啥是false?
哈哈。 。 。
雙等號,如果兩邊類型不同,會有隱式轉換發生。犀牛書75頁總結如下:

1,null和undefined,相等。
2,数字和字符串,转化为数字再比较。
3,如果有true或false,转换为1或0,再比较。
4,如果有引用类型,优先调用valueOf。
5,其余都不相等。

因此有:

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

0 == false之所以為true根據第3條。
"" == false之所以為true根據第3條,變成了"" == 0,再根據第2條。
第4條再來一個例子:

console.log([[2]] == 2)

其上結果為true,原因如下:
[[2]]的valueOf是物件本身,不是基本型別。
嘗試呼叫toString的結果是'2'。
因此變成了'2'和數字2的比較。根據第2條,相等。 WTF!!
最後說句,使用"==="就沒有這些問題了。
本文完。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn