摘要:函數不是函數這是一個低版本的,,或則。對應的進制數為。因此最安全的方法是調用的時候指定進制。它會將字符串形式的整數轉換為,非字符串的,,和也會被轉換。對于不能轉換的值,返回。而瀏覽器主要指系列,其實已經沒有必要支持這個特性了。
譯者按: JavaScript有很多坑,經常一不小心就要寫bug。
原文: What the f*ck JavaScript?
譯者: Fundebug
為了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原作者所有,翻譯僅用于學習。
JavaScript是一門偉大的語言,它擁有非常簡潔的語法,龐大的生態系統,以及最重要的:有一個偉大的社區支撐著。同時,我們也知道JavaScript是一個充滿技巧性的語言。有些坑足以讓我們崩潰,也有些奇淫技巧讓我們覺得很有趣。本文的思想源自于Brian Leroux在dotJS2012上的演講“WTFJS” at dotJS 2012。
我收集這些例子的主要目的是將它們整理并清楚理解它們的原理。從中學到很多以前不懂的知識是一件很有趣的事情。如果你是初學者,你可以通過學習這些筆記深入理解JavaScript;如果你是一個專業的開發者,那么可以將這些筆記作為一個不錯的引用資料。不管怎樣,只要讀下去,你就會學到新東西的。
函數不是函數??? 這是一個低版本的bug,V8(<=5.5),或則Node.js(<=7)。
// Declare a class which extends null class Foo extends null {} // -> [Function: Foo] new Foo instanceof null // > TypeError: function is not a function // > at … … …
備注:經測試高版本(Node.js, v8.1.1)不會出現這個bug。如果你還沒升級到高版本,不妨試一下看看?
數組相加如果我們將兩個數組相加,結果會怎樣?
[1, 2, 3] + [4, 5, 6] // -> "1,2,34,5,6"
實際上是做了拼接操作,我們來一步一步解釋:
[1, 2, 3] + [4, 5, 6] // 調用 toString() [1, 2, 3].toString() + [4, 5, 6].toString() // 字符串拼接 "1,2,3" + "4,5,6" // -> "1,2,34,5,6"數組中分號的去除
我們創建一個4個空元素的數組。結果呢,該數組實際上只有3個元素,因為最后一個分號被去掉了。
let a = [,,,] a.length // -> 3 a.toString() // -> ",,"
末尾分號(Trailing commas)(又叫做final commas)在添加新元素、參數或則屬性時候很有用。如果你想增加一個新的屬性,并且前一行末尾有使用分號,你可以直接在新的一行添加而不用修改前一行。這可以讓版本控制的diff操作更加清晰,代碼更少出問題。- Trailing commas at MDN數組相等匹配非??植?/b>
請看:
[] == "" // -> true [] == 0 // -> true [""] == "" // -> true [0] == 0 // -> true [0] == "" // -> false [""] == 0 // -> true [null] == "" // true [null] == 0 // true [undefined] == "" // true [undefined] == 0 // true [[]] == 0 // true [[]] == "" // true [[[[[[]]]]]] == "" // true [[[[[[]]]]]] == 0 // true [[[[[[ null ]]]]]] == 0 // true [[[[[[ null ]]]]]] == "" // true [[[[[[ undefined ]]]]]] == 0 // true [[[[[[ undefined ]]]]]] == "" // true
具體請參考7.2.13 Abstract Equality Comparison
undefined和Number如果不給Number構造函數傳入任何參數,那么返回0。如果傳入undefined作為參數,會返回NaN。
Number() // -> 0 Number(undefined) // -> NaN
根據規范:
如果沒有參數傳入,那么n=0;
否則,n= ToNumber(value);
如果value為undefined,那么ToNumnber(undefined)為NaN。
參考:
20.1.1 The Number Constructor
7.1.3 ToNumber(argument)
JavaScript坑很多,趕緊使用fundebug扶一扶!
parseInt也不是個好東西parseInt因為它奇怪的行為而出名:
parseInt("f*ck"); // -> NaN parseInt("f*ck", 16); // -> 15
這是因為parseInt一個字符一個字符去分析,知道遇到無法處理的字符。f對應的16進制數為15。
Infinity可以轉換為對應的數字:
// parseInt("Infinity", 10) // -> NaN // ... parseInt("Infinity", 18) // -> NaN... parseInt("Infinity", 19) // -> 18 // ... parseInt("Infinity", 23) // -> 18... parseInt("Infinity", 24) // -> 151176378 // ... parseInt("Infinity", 29) // -> 385849803 parseInt("Infinity", 30) // -> 13693557269 // ... parseInt("Infinity", 34) // -> 28872273981 parseInt("Infinity", 35) // -> 1201203301724 parseInt("Infinity", 36) // -> 1461559270678... parseInt("Infinity", 37) // -> NaN
小心參數為null的情況:
parseInt(null, 24) // -> 23
首先,null被翻譯為字符串"null"。"n"在24進制中對于23。-- 更多請參考 “parseInt(null, 24) === 23… wait, what?” at StackOverflow。
parseInt("n", 24) // -> 23
不要忘記了8進制:
parseInt("06"); // 6 parseInt("08"); // 8 if support ECMAScript 5 parseInt("08"); // 0 if not support ECMAScript 5
如果輸入的字符串以0開始,那么為8進制或則10進制。到底是哪一個,要看實現。如果是ECMAScript5,則為10進制。但并不是所有瀏覽器都支持。因此最安全的方法是調用parseInt的時候指定進制。
parseInt總是將輸入轉換為字符串。
parseInt({ toString: () => 2, valueOf: () => 1 }) // -> 2 Number({ toString: () => 2, valueOf: () => 1 }) // -> 1true和false的數學運算
true + true // -> 2 (true + true) * (true + true) - true // -> 3
我們把true轉換為Number來看看就明白了:
Number(true) // -> 1
一元加號運算會嘗試將參數轉換為number。它會將字符串形式的整數轉換為float,非字符串的true,false,和null也會被轉換。對于不能轉換的值,返回NaN。因此,我們有了一個更加簡單的轉換方法:
+true // -> 1
當你使用加法或則乘法的時候,ToNumber函數會被調用。根據定義:
如果參數為true,返回1. 如果參數為false,返回+0.
這就是為什么我們布爾類型的值(true,false)可以和數字相加。
參考:
12.5.6 Unary + Operator
12.8.3 The Addition Operator (+)
7.1.3 ToNumber(argument)
JavaScript中可以使用HTML的評論方式在JavaScript中,使用