最近遇到一個讓人困解的一個問題;一個簡單的js加法運算表達式:
1 +[]; //這里加上一個空數組得到什么???
答案:'1';
為什么答案是1,一開始我也很困惑;后來我讀了一篇文章才知道:在javascript中加法的規則很簡單,只能數字與數字相加或字符串和字符串相加;所有其他類型的值都會自動轉換成這兩個類型的值。這里面其實有一個隱式轉換的存在。這里就不得不說javascript的兩種類型的值了;即原始值和對象值(或者說引用類型的值),原始值有undefined,null,boolean,number,String;而其他的值都是對象值包括數組(Array)和函數(function);判斷一個值是否是原始類型的值的話可以使用typeof,判斷是否是對象值的話可以使用instanceOf;這里要注意的是typeof null;//'object'得到的是object;這里w3School上的解釋是javascript最初實現的一個錯誤,然后被ECMAScript沿用了。現在null被認為是對象的占位符,從而解釋了這一矛盾。但從技術上來說null仍是原始值。
類型轉換
javascript中加法會觸發3種類型轉換;即將值轉換為原始值,轉換為字符串,轉換為數字。這剛好對應了javascript引擎內部的轉換操作:ToPrimitive(),toString(),toNumber;
所以這里:1 + [] = '1';即[].toString() = ''; 然后1 + '' = '1';即把1轉換成字符串,'1' + '' = '1' 最后就是兩個字符串連接成的字符串;(詳細可見w3School中的javascript加法運算http://www.w3school.com.cn/js/pro_js_operators_additive.asp)
明白了這個接下來的加法運算也就一目了然了:
+[] = 0; //其實就是Number([]),當Number作為一個函數調用(而不是作為構造函數調用時)會在引擎內部執行toNumber操作 +{} = NaN; // Number('[object,object]'); -->NaN 即String({})='[object,object]'; +'[object, object]' = NaN 1 + [1] = '11'; // String({}) = '1' --> '1' + '1' = '11' 1 + [1, 2] = '11,2'; // String([1,2]) = '1,2' ---> '1' + '1,2' = '11,2'; 1+ {} = '1[object,object]'; String({}) = '[object, object]' ---> '1' + '[object, object]' = '1[object,object]';
[]+[] = ''; // 其實就是String([]) = '';---> '' + '' = '';
[]+{} = '[object,object]'; //同上String([]) = '', String({}) = '[object,object]' ---> '' + '[object, object]' = '[object, object]';
{} + {} = NaN;//這里值得注意的是javascript會把第一個{}解釋成一個空塊並忽略了它所以這里等價於+{}
參考:http://www.2ality.com/2011/03/javascript-values-not-everything-is.html