摘要:本文的思想源自于在上的演講。我收集這些例子的主要目的是將它們整理并清楚理解它們的原理。著主要是因?yàn)榇罄ㄌ?hào)也是函數(shù)定義語法的一部分。自從年雙十一正式上線,累計(jì)處理了億錯(cuò)誤事件,得到了金山軟件等眾多知名用戶的認(rèn)可。
譯者按: JavaScript有很多坑,經(jīng)常一不小心就要寫bug。
原文: What the f*ck JavaScript?
譯者: Fundebug
為了保證可讀性,本文采用意譯而非直譯。另外,本文版權(quán)歸原作者所有,翻譯僅用于學(xué)習(xí)。
JavaScript是一門偉大的語言,它擁有非常簡(jiǎn)潔的語法,龐大的生態(tài)系統(tǒng),以及最重要的:有一個(gè)偉大的社區(qū)支撐著。同時(shí),我們也知道JavaScript是一個(gè)充滿技巧性的語言。有些坑足以讓我們崩潰,也有些奇淫技巧讓我們覺得很有趣。本文的思想源自于Brian Leroux在dotJS2012上的演講“WTFJS” at dotJS 2012。
我收集這些例子的主要目的是將它們整理并清楚理解它們的原理。從中學(xué)到很多以前不懂的知識(shí)是一件很有趣的事情。如果你是初學(xué)者,你可以通過學(xué)習(xí)這些筆記深入理解JavaScript;如果你是一個(gè)專業(yè)的開發(fā)者,那么可以將這些筆記作為一個(gè)不錯(cuò)的引用資料。不管怎樣,只要讀下去,你就會(huì)學(xué)到新東西的。
return下面的函數(shù)返回的結(jié)果竟然不是對(duì)象{b:10}:
(function () { return { b : 10 } })() // -> undefined
不過,如果稍微改寫一下,就不一樣了:
(function () { return { b : 10 } })() // -> { b: 10 }
這主要是因?yàn)橛幸粋€(gè)自動(dòng)行尾加分號(hào)的機(jī)制在作怪,會(huì)自動(dòng)在很多新行的行尾添加分號(hào)。在第一個(gè)例子中,實(shí)際上是在return后面添加了分號(hào)。
(function () { return ; { b : 10 } })() // -> undefined
JavaScript坑很多,趕緊使用fundebug扶一扶!
0.1+0.2=?一個(gè)眾所周知的笑話就是0.1加上0.2竟然不等于0.3。
0.1 + 0.2 // -> 0.30000000000000004 (0.1 + 0.2) === 0.3 // -> false
在StackOverflow上有關(guān)提到這樣的問題“浮點(diǎn)數(shù)加法運(yùn)算壞了(Is floating point math broken?)”:
你的程序中0.2和0.3會(huì)在底層用相近的數(shù)據(jù)表達(dá)。double類型數(shù)據(jù)中離0.2最近的數(shù)要比0.2大一點(diǎn)點(diǎn)。離0.3最近的double類型數(shù)據(jù)又剛好比0.3小一點(diǎn)點(diǎn)。所以,結(jié)果就是0.1+0.2的結(jié)果比0.3大。
這個(gè)問題非常出名,以至于有一個(gè)專門的網(wǎng)站0.30000000000000004.com。在所有使用浮點(diǎn)計(jì)算的語言中都有這個(gè)問題,不止JavaScript。
神奇的加法操作999999999999999 // -> 999999999999999 9999999999999999 // -> 10000000000000000 10000000000000000 // -> 10000000000000000 10000000000000000 + 1 // -> 10000000000000000 10000000000000000 + 1.1 // -> 10000000000000002
這個(gè)是依據(jù)IEEE 754-2008標(biāo)準(zhǔn)確定的二進(jìn)制浮點(diǎn)運(yùn)算。當(dāng)數(shù)值大到這個(gè)程度,它會(huì)取整到最近的偶數(shù)。參考:
6.1.6 The Number Type
IEEE 754 on Wikipedia
為Number自定義你可以為Number和String添加自定義函數(shù):
Number.prototype.isOne = function () { return Number(this) === 1 } 1.0.isOne() // -> true 1..isOne() // -> true 2.0.isOne() // -> false (7).isOne() // -> false
你可以想操縱其它對(duì)象一樣去擴(kuò)展Number對(duì)象。不過,如果定義的函數(shù)不在它本身的定義規(guī)范(Specification)中,那么不建議這么做。這里是一個(gè)參考列表:
20.1 Number Objects
3個(gè)number比較1 < 2 < 3 // -> true 3 > 2 > 1 // -> false
我們來看看具體的執(zhí)行過程就明白了:
1 < 2 < 3 // 1 < 2 -> true true < 3 // true -> 1 1 < 3 // -> true 3 > 2 > 1 // 3 > 2 -> true true > 1 // true -> 1 1 > 1 // -> false有趣的數(shù)學(xué)
3 - 1 // -> 2 3 + 1 // -> 4 "3" - 1 // -> 2 "3" + 1 // -> "31" "" + "" // -> "" [] + [] // -> "" {} + [] // -> 0 [] + {} // -> "[object Object]" {} + {} // -> "[object Object][object Object]" "222" - -"111" // -> 333 [4] * [4] // -> 16 [] * [] // -> 0 [4, 4] * [4, 4] // NaN
到底是為什么呢? 下面有一個(gè)表供快速參考:
Number + Number -> addition Boolean + Number -> addition Boolean + Boolean -> addition Number + String -> concatenation String + Boolean -> concatenation String + String -> concatenation
那么其他例子呢?對(duì)于[]和{},toPrimitive和toString方法會(huì)在加法操作前被隱式地調(diào)用。
12.8.3 The Addition Operator (+)
[7.1.1 ToPrimitive(input [,PreferredType])](https://www.ecma-internationa...
7.1.12 ToString(argument)
正則也可以做加法?// Patch a toString method RegExp.prototype.toString = function() { return this.source } /7/ - /5/ // -> 2
參考: 21.2.5.10 get RegExp.prototype.source
箭頭函數(shù)let f = () => 10 f() // -> 10
好的,但是下面這個(gè)呢:
let f = () => {} f() // -> undefined
你也許期待著返回{},而不是undefined。著主要是因?yàn)榇罄ㄌ?hào)也是函數(shù)定義語法的一部分。如果你真想返回大括號(hào),可以這么寫:
let f = () => ({}) f() // -> {}Math.max()比Math.min()小
Math.min(1,4,7,2) // -> 1 Math.max(1,4,7,2) // -> 7 Math.min() // -> Infinity Math.max() // -> -Infinity Math.min() > Math.max() // -> true
原因: Why is Math.max() less than Math.min()? by Charlie Harvey
String不是String的實(shí)例"str" // -> "str" typeof "str" // -> "string" "str" instanceof String // -> false
構(gòu)造函數(shù)String返回一個(gè)字符串:
typeof String("str") // -> "string" String("str") // -> "str" String("str") == "str" // -> true
如果我們用new來構(gòu)建的話:
new String("str") == "str" // -> true typeof new String("str") // -> "object"
竟然變成了一個(gè)對(duì)象!
new String("str") // -> [String: "str"]
參考: 21.1.1 The String Constructor
往期參考Fundebug博客 - 怪異的JavaScript系列(一)
Fundebug博客 - 怪異的JavaScript系列(二)
關(guān)于FundebugFundebug專注于JavaScript、微信小程序、微信小游戲、支付寶小程序、React Native、Node.js和Java實(shí)時(shí)BUG監(jiān)控。 自從2016年雙十一正式上線,F(xiàn)undebug累計(jì)處理了6億+錯(cuò)誤事件,得到了Google、360、金山軟件等眾多知名用戶的認(rèn)可。歡迎免費(fèi)試用!
版權(quán)聲明轉(zhuǎn)載時(shí)請(qǐng)注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2018/04/16/javascript-werid-series-3/
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94608.html
摘要:知識(shí)點(diǎn)一和瀏覽器渲染模式文檔類型,一個(gè)文檔類型標(biāo)記是一種標(biāo)準(zhǔn)通用標(biāo)記語言的文檔類型聲明,它的目的是要告訴標(biāo)準(zhǔn)通用標(biāo)記語言解析器,它應(yīng)該使用什么樣的文檔類型定義來解析文檔。知識(shí)點(diǎn)二文件類型聲明僅有一型。知識(shí)點(diǎn)三常用整理常用整理 知識(shí)點(diǎn)一:DOCTYPE和瀏覽器渲染模式 文檔類型,一個(gè)文檔類型標(biāo)記是一種標(biāo)準(zhǔn)通用標(biāo)記語言的文檔類型聲明,它的目的是要告訴標(biāo)準(zhǔn)通用標(biāo)記語言解析器,它應(yīng)該使用什么樣...
摘要:知識(shí)點(diǎn)一和瀏覽器渲染模式文檔類型,一個(gè)文檔類型標(biāo)記是一種標(biāo)準(zhǔn)通用標(biāo)記語言的文檔類型聲明,它的目的是要告訴標(biāo)準(zhǔn)通用標(biāo)記語言解析器,它應(yīng)該使用什么樣的文檔類型定義來解析文檔。知識(shí)點(diǎn)二文件類型聲明僅有一型。知識(shí)點(diǎn)三常用整理常用整理 知識(shí)點(diǎn)一:DOCTYPE和瀏覽器渲染模式 文檔類型,一個(gè)文檔類型標(biāo)記是一種標(biāo)準(zhǔn)通用標(biāo)記語言的文檔類型聲明,它的目的是要告訴標(biāo)準(zhǔn)通用標(biāo)記語言解析器,它應(yīng)該使用什么樣...
摘要:知識(shí)點(diǎn)一和瀏覽器渲染模式文檔類型,一個(gè)文檔類型標(biāo)記是一種標(biāo)準(zhǔn)通用標(biāo)記語言的文檔類型聲明,它的目的是要告訴標(biāo)準(zhǔn)通用標(biāo)記語言解析器,它應(yīng)該使用什么樣的文檔類型定義來解析文檔。知識(shí)點(diǎn)二文件類型聲明僅有一型。知識(shí)點(diǎn)三常用整理常用整理 知識(shí)點(diǎn)一:DOCTYPE和瀏覽器渲染模式 文檔類型,一個(gè)文檔類型標(biāo)記是一種標(biāo)準(zhǔn)通用標(biāo)記語言的文檔類型聲明,它的目的是要告訴標(biāo)準(zhǔn)通用標(biāo)記語言解析器,它應(yīng)該使用什么樣...
摘要:函數(shù)不是函數(shù)這是一個(gè)低版本的,,或則。對(duì)應(yīng)的進(jìn)制數(shù)為。因此最安全的方法是調(diào)用的時(shí)候指定進(jìn)制。它會(huì)將字符串形式的整數(shù)轉(zhuǎn)換為,非字符串的,,和也會(huì)被轉(zhuǎn)換。對(duì)于不能轉(zhuǎn)換的值,返回。而瀏覽器主要指系列,其實(shí)已經(jīng)沒有必要支持這個(gè)特性了。 譯者按: JavaScript有很多坑,經(jīng)常一不小心就要寫bug。 原文: What the f*ck JavaScript? 譯者: Fundebug ...
閱讀 970·2021-10-27 14:14
閱讀 1771·2021-10-11 10:59
閱讀 1344·2019-08-30 13:13
閱讀 3184·2019-08-29 15:17
閱讀 2778·2019-08-29 13:48
閱讀 514·2019-08-26 13:36
閱讀 2108·2019-08-26 13:25
閱讀 878·2019-08-26 12:24