奇異的JavaScript系列(二)

譯者按: JavaScript有許多坑,常常一不警惕就要寫bug。

為了保證可讀性,本文採納意譯而非直譯。別的,本文版權歸原作者一切,翻譯僅用於進修。

JavaScript是一門巨大的言語,它具有異常簡約的語法,巨大的生態系統,以及最重要的:有一個巨大的社區支撐着。同時,我們也曉得JavaScript是一個充溢技能性的言語。有些坑足以讓我們崩潰,也有些奇淫技能讓我們覺得很風趣。本文的頭腦源自於Brian Leroux在dotJS2012上的演講“WTFJS” at dotJS 2012

《奇異的JavaScript系列(二)》

我網絡這些例子的重要目標是將它們整頓並清楚邃曉它們的道理。從中學到許多之前不懂的學問是一件很風趣的事變。假如你是初學者,你能夠經由過程進修這些筆記深切邃曉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

數組相稱婚配異常恐懼

請看:

[] == ''   // -> 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

依據範例:

  1. 假如沒有參數傳入,那末n=0;
  2. 不然,n= ToNumber(value);
  3. 假如value為undefined,那末ToNumnber(undefined)為NaN。

參考:

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 })   // -> 1

true和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)能夠和数字相加。

參考:

JavaScript中能夠運用HTML的批評體式格局

在JavaScript中,運用<!--是一個有用的批評體式格局。

// valid comment
<!-- valid comment too

支撐HTML的批評體式格局的目標是許可那些不支撐<script>標籤的瀏覽器能夠文雅地降級。而瀏覽器重要指Netscape 1.x系列,實在已沒有必要支撐這個特徵了。

Node.js也是基於V8完成,所以在Node.js中也能夠運用。

參考:B.1.3 HTML-like Comments

NaN是Number

NaN的範例是’number’:

typeof NaN // -> 'number'

假如想相識typeof和instanceof怎樣事情,參考:

[]和null是對象

typeof []   // -> 'object'
typeof null // -> 'object'

// 然則
null instanceof Object // false

依據typeof的定義,關於null,作為一個沒有完成[[Call]]的對象,返回”object”。

你能夠用toString函數來搜檢對象的詳細(Array, Date, Null)範例:

Object.prototype.toString.call([])
// -> '[object Array]'

Object.prototype.toString.call(new Date)
// -> '[object Date]'

Object.prototype.toString.call(null)
// -> '[object Null]'
    原文作者:Fundebug
    原文地址: https://segmentfault.com/a/1190000014577895
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞