25 道有趣的 JavaScript 題目,你能答對幾個?
題目
1. true + false
Number(true);?//?->?1
Number(false);?//?->?0
1?+?0;?//?->?1
?? 說明:
布爾值被轉(zhuǎn)換為它們的數(shù)字表示
2. true 是 false
!!"false"?==?!!"true";?//?->?true
!!"false"?===?!!"true";?//?->?true
?? 說明:
考慮一下這一步:
true?==?"true";?//?->?true
false?==?"false";?//?->?false
//?'false'?不是空字符串,所以它的值是?true
!!"false";?//?->?true
!!"true";?//?->?true
3. baNaNa
"b"?+?"a"?+?+"a"?+?"a";?//?baNaNa
用 JavaScript 寫的老派笑話:
"foo"?+?+"bar";?//?->?'fooNaN'
?? 說明:
這個表達(dá)式可以轉(zhuǎn)化成 'foo' + (+'bar'),但無法將'bar'強(qiáng)制轉(zhuǎn)化成數(shù)值。
4. NaN 不是一個 NaN
NaN?===?NaN;?//?->?false
?? 說明:
規(guī)范嚴(yán)格定義了這種行為背后的邏輯:
- 如果
Type(x)不同于Type(y), return false.- 如果
Type(x)數(shù)值, 然后
- 如果
x是 NaN, return false.- 如果
y是 NaN, return false.- … … …
遵循 IEEE 的“NaN”的定義:
有四種可能的相互排斥的關(guān)系:小于,等于,大于和無序。當(dāng)至少一個操作數(shù)是 NaN 時,便是最后一種情況。每個 NaN 都要比較無窮無盡的一切,包括自己。
5. 它是 fail
你不會相信,但...
(![]?+?[])[+[]]?+
??(![]?+?[])[+!+[]]?+
??([![]]?+?[][[]])[+!+[]?+?[+[]]]?+
??(![]?+?[])[!+[]?+?!+[]];
//?->?'fail'
?? 說明:
將大量的符號分解成片段,我們注意到,以下表達(dá)式經(jīng)常出現(xiàn):
![]?+?[];?//?->?'false'
![];?//?->?false
所以我們嘗試將[]和false加起來。但是通過一些內(nèi)部函數(shù)調(diào)用(binary + Operator - >ToPrimitive - >[[DefaultValue] ]),我們最終將右邊的操作數(shù)轉(zhuǎn)換為一個字符串:
![]?+?[].toString();?//?'false'
將字符串作為數(shù)組,我們可以通過[0]來訪問它的第一個字符:
"false"[0];?//?->?'f'
現(xiàn)在,其余的是明顯的,可以自己弄清楚!
6. [] 是 true, 但它不等于 true
!![]???????//?->?true
[]?==?true?//?->?false
?? 說明:
數(shù)組是一個true,但是它不等于true。
7. null 是 false, 但又不等于 false
盡管 null 是 false,但它不等于 false。
!!null;?//?->?false
null?==?false;?//?->?false
同時,其他的一些等于 false 的值,如 0 或 '' 等于 false 。
0?==?false;?//?->?true
""?==?false;?//?->?true
?? 說明:
跟前面的例子相同。這是一個相應(yīng)的鏈接:
- 7.2.13 抽象相等比較
8. document.all 是一個 object,但又同時是 undefined
?? 這是瀏覽器 API 的一部分,對于 Node.js 環(huán)境無效 ??
盡管 document.all 是一個 array-like object 并且通過它可以訪問頁面中的 DOM 節(jié)點(diǎn),但在通過 typeof 的檢測結(jié)果是 undefined。
document.all?instanceof?Object;?//?->?true
typeof?document.all;?//?->?'undefined'
同時,document.all 不等于 undefined。
document.all?===?undefined;?//?->?false
document.all?===?null;?//?->?false
但是同時:
document.all?==?null;?//?->?true
?? 說明:
document.all曾經(jīng)是訪問頁面 DOM 節(jié)點(diǎn)的一種方式,特別是在早期版本的 IE 瀏覽器中。它從未成為標(biāo)準(zhǔn),但被廣泛使用在早期的 JS 代碼中。當(dāng)標(biāo)準(zhǔn)演變出新的 API 時(例如document.getElementById)這個 API 調(diào)用就被廢棄了,標(biāo)準(zhǔn)委員會必須決定如何處理它。因?yàn)樗粡V泛使用嗯他們決定保留這個 API 但引入一個有意的對 JavaScript 的標(biāo)準(zhǔn)的違反。其與undefined使用嚴(yán)格相等比較得出false而使用抽象相等比較 得出true是因?yàn)檫@個有意的對標(biāo)準(zhǔn)的違反明確地允許了這一點(diǎn)。
9. 最小值大于零
Number.MIN_VALUE 是最小的數(shù)字,大于零:
Number.MIN_VALUE?>?0;?//?->?true
?? 說明:
Number.MIN_VALUE是5e-324,即可以在浮點(diǎn)精度內(nèi)表示的最小正數(shù),即可以達(dá)到零。它定義了浮點(diǎn)數(shù)的最高精度。
現(xiàn)在,整體最小的值是
Number.NEGATIVE_INFINITY,盡管這在嚴(yán)格意義上并不是真正的數(shù)字。
10. 函數(shù)不是函數(shù)
?? V8 v5.5 或更低版本中出現(xiàn)的 Bug(Node.js <= 7) ??
你們所有人都知道的關(guān)于討厭的 undefined 不是 function ,但是這個呢?
//?Declare?a?class?which?extends?null
class?Foo?extends?null?{}
//?->?[Function:?Foo]
new?Foo()?instanceof?null;
//?>?TypeError:?function?is?not?a?function
//?>?????at?…?…?…
?? 說明:
這不是規(guī)范的一部分。這只是一個錯誤,現(xiàn)在它已被修復(fù),所以將來不會有這個問題。
11. 數(shù)組相加
如果您嘗試兩個數(shù)組相加呢?
[1,?2,?3]?+?[4,?5,?6];?//?->?'1,2,34,5,6'
?? 說明:
會發(fā)生合并。一步一步地,它是這樣的:
[1,?2,?3]?+
??[4,?5,?6][
????//?joining
????(1,?2,?3)
??].join()?+
??[4,?5,?6].join();
//?concatenation
"1,2,3"?+?"4,5,6";
//?->
("1,2,34,5,6");
12. 數(shù)組中的逗號
您已經(jīng)創(chuàng)建了一個包含 4 個空元素的數(shù)組。盡管如此,你還是會得到一個有三個元素的,因?yàn)楹竺娴亩禾枺?/p>
let?a?=?[,?,?,];
a.length;?//?->?3
a.toString();?//?->?',,'
?? 說明:
尾逗號 (有時也稱為“最后逗號”) 在向 JavaScript 代碼中添加新元素、參數(shù)或?qū)傩詴r有用。如果您想添加一個新屬性,您可以簡單地添加一個新行,而不用修改以前的最后一行,如果該行已經(jīng)使用了后面的逗號。這使得版本控制比較清潔和編輯代碼可能不太麻煩。
13. 數(shù)組相等是一個怪物
數(shù)組進(jìn)行相等比較是一個怪物,看下面的例子:
[]?==?''???//?->?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
?? 說明:
你應(yīng)該非常小心留意上面的例子!7.2.13 Abstract Equality Comparison 規(guī)范描述了這些行為。
14. undefined 和 Number
如果我們不把任何參數(shù)傳遞到 Number 構(gòu)造函數(shù)中,我們將得到 0 。undefined 是一個賦值形參,沒有實(shí)際的參數(shù),所以您可能期望 NaN 將 undefined 作為參數(shù)的值。然而,當(dāng)我們通過 undefined ,我們將得到 NaN 。
Number();?//?->?0
Number(undefined);?//?->?NaN
?? 說明:
根據(jù)規(guī)范:
- 如果沒有參數(shù)傳遞給這個函數(shù),讓
n為+0; - 否則,讓
n調(diào)用ToNumber(value) - 如果值為
undefined,那么ToNumber(undefined)應(yīng)該返回NaN.
15. parseInt 是一個壞蛋
parseInt 它以的怪異而出名。
parseInt("f*ck");?//?->?NaN
parseInt("f*ck",?16);?//?->?15
**?? 說明:
** 這是因?yàn)?parseInt 會持續(xù)通過解析直到它解析到一個不識別的字符,'f*ck' 中的 f 是 16 進(jìn)制下的 15。
解析 Infinity 到整數(shù)也很有意思…
//
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轉(zhuǎn)換成字符串'null',并嘗試轉(zhuǎn)換它。對于基數(shù) 0 到 23,沒有可以轉(zhuǎn)換的數(shù)字,因此返回 NaN。在 24,“n”,第 14 個字母被添加到數(shù)字系統(tǒng)。在 31,“u”,添加第 21 個字母,可以解碼整個字符串。在 37 處,不再有可以生成的有效數(shù)字集,并返回NaN。
不要忘記八進(jìn)制:
parseInt("06");?//?6
parseInt("08");?//?8?如果支持?ECMAScript?5
parseInt("08");?//?0?如果不支持?ECMAScript?5
?? 說明:
這是因?yàn)?parseInt 能夠接受兩個參數(shù),如果沒有提供第二個參數(shù),并且第一個參數(shù)以 0 開始,它將把第一個參數(shù)當(dāng)做八進(jìn)制數(shù)解析。
parseInt 總是把輸入轉(zhuǎn)為字符串:
parseInt({?toString:?()?=>?2,?valueOf:?()?=>?1?});?//?->?2
Number({?toString:?()?=>?2,?valueOf:?()?=>?1?});?//?->?1
解析浮點(diǎn)數(shù)的時候要注意
parseInt(0.000001);?//?->?0
parseInt(0.0000001);?//?->?1
parseInt(1?/?1999999);?//?->?5
?? 說明: ParseInt 接受字符串參數(shù)并返回一個指定基數(shù)下的證書。ParseInt 也去除第一個字符串中非數(shù)字字符(字符集由基數(shù)決定)后的內(nèi)容。0.000001 被轉(zhuǎn)換為 "0.000001" 而 parseInt 返回 0。當(dāng) 0.0000001 被轉(zhuǎn)換為字符串時它被處理為 "1e-7" 因此 parseInt 返回 1。1/1999999 被轉(zhuǎn)換為 5.00000250000125e-7 而 parseInt 返回 5。
16. true 和 false 數(shù)學(xué)運(yùn)算
我們做一些數(shù)學(xué)計(jì)算:
true?+
??true(
????//?->?2
????true?+?true
??)?*
????(true?+?true)?-
??true;?//?->?3
嗯… ??
?? 說明:
我們可以用 Number 構(gòu)造函數(shù)強(qiáng)制轉(zhuǎn)化成數(shù)值。很明顯,true 將被強(qiáng)制轉(zhuǎn)換為 1 :
Number(true);?//?->?1
一元加運(yùn)算符嘗試將其值轉(zhuǎn)換成數(shù)字。它可以轉(zhuǎn)換整數(shù)和浮點(diǎn)的字符串表示,以及非字符串值 true ,false 和 null 。如果它不能解析特定的值,它將轉(zhuǎn)化為 NaN 。這意味著我們可以更容易地強(qiáng)制將 true 換成 1
+true;?//?->?1
當(dāng)你執(zhí)行加法或乘法時,ToNumber方法調(diào)用。根據(jù)規(guī)范,該方法返回:
如果
參數(shù)is true , 返回 1 。如果參數(shù)是 false 返回 +0。
這就是為什么我們可以進(jìn)行進(jìn)行布爾值相加并得到正確的結(jié)果
相應(yīng)部分:
- 12.5.6 一元
+運(yùn)算符 - 12.8.3 加法運(yùn)算符(
+) - 7.1.3 ToNumber(
argument)
17. HTML 注釋在 JavaScript 中有效
你會留下深刻的印象,<!-- (這是 HTML 注釋)是一個有效的 JavaScript 注釋。
//?有效注釋
<!--?也是有效的注釋
?? 說明:
感動嗎? 類似 HTML 的注釋旨在允許不理解標(biāo)簽的瀏覽器優(yōu)雅地降級。這些瀏覽器,例如 Netscape 1.x 已經(jīng)不再流行。因此,在腳本標(biāo)記中添加 HTML 注釋是沒有意義的。
由于 Node.js 基于 V8 引擎,Node.js 運(yùn)行時也支持類似 HTML 的注釋。
18. NaN 不是一個數(shù)值
盡管 NaN 類型是 'number' ,但是 NaN 不是數(shù)字的實(shí)例:
typeof?NaN;?//?->?'number'
NaN?instanceof?Number;?//?->?false
?? 說明:
typeof 和 instanceof 運(yùn)算符的工作原理:
- 12.5.5
typeof操作符 - 12.10.4 Runtime Semantics: InstanceofOperator(
O,C)
19. [] 和 null 是對象
typeof?[];?//?->?'object'
typeof?null;?//?->?'object'
//?然而
null?instanceof?Object;?//?false
?? 說明:
typeof 運(yùn)算符的行為在本節(jié)的規(guī)范中定義:
根據(jù)規(guī)范,typeof 操作符返回一個字符串 。對于沒有 [[Call]] 實(shí)現(xiàn)的 null、普通對象、標(biāo)準(zhǔn)特異對象和非標(biāo)準(zhǔn)特異對象,它返回字符串 "object“。
但是,您可以使用 toString 方法檢查對象的類型。
Object.prototype.toString.call([]);
//?->?'[object?Array]'
Object.prototype.toString.call(new?Date());
//?->?'[object?Date]'
Object.prototype.toString.call(null);
//?->?'[object?Null]'
20. 神奇的數(shù)字增長
999999999999999;?//?->?999999999999999
9999999999999999;?//?->?10000000000000000
?? 說明:
這是由 IEEE 754-2008 二進(jìn)制浮點(diǎn)運(yùn)算標(biāo)準(zhǔn)引起的。
21. 0.1 + 0.2 精度計(jì)算
來自 JavaScript 的知名笑話。0.1 和 0.2 相加是存在精度錯誤的
0.1?+
??0.2(
????//?->?0.30000000000000004
????0.1?+?0.2
??)?===
??0.3;?//?->?false
?? 說明:
浮點(diǎn)計(jì)算壞了:
程序中的常量
0.2和0.3也將近似為真實(shí)值。最接近0.2的double大于有理數(shù)0.2,但最接近0.3的double小于有理數(shù)0.3。0.1和0.2的總和大于有理數(shù)0.3,因此不符合您的代碼中的常數(shù)判斷。
這個問題是眾所周知的,甚至有一個網(wǎng)站叫 0.30000000000000004.com。
22. 擴(kuò)展數(shù)字的方法
您可以添加自己的方法來包裝對象,如 Number 或 String 。
Number.prototype.isOne?=?function()?{
??return?Number(this)?===?1;
};
(1.0).isOne();?//?->?true
(1).isOne();?//?->?true
(2.0)
??.isOne()(
????//?->?false
????7
??)
??.isOne();?//?->?false
?? 說明:
顯然,您可以像 JavaScript 中的任何其他對象一樣擴(kuò)展 Number 對象。但是,不建議擴(kuò)展不屬于規(guī)范的行為定義。以下是 Number 屬性的列表:
23. 三個數(shù)字的比較
1?<?2?<?3;?//?->?true
3?>?2?>?1;?//?->?false
?? 說明:
為什么會這樣呢?其實(shí)問題在于表達(dá)式的第一部分。以下是它的工作原理:
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
我們可以用 大于或等于運(yùn)算符(>=):
3?>?2?>=?1;?//?true
24. 有趣的數(shù)學(xué)
通常 JavaScript 中的算術(shù)運(yùn)算的結(jié)果可能是非常難以預(yù)料的??紤]這些例子:
?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
?? 說明:
前四個例子發(fā)生了什么?這是一個小表,以了解 JavaScript 中的添加:
Number??+?Number??->?addition
Boolean?+?Number??->?addition
Boolean?+?Boolean?->?addition
Number??+?String??->?concatenation
String??+?Boolean?->?concatenation
String??+?String??->?concatenation
剩下的例子呢?在相加之前,[] 和 {} 隱式調(diào)用 ToPrimitive 和 ToString 方法。
25. 字符串不是 String 的實(shí)例
"str";?//?->?'str'
typeof?"str";?//?->?'string'
"str"?instanceof?String;?//?->?false
?? 說明:
String 構(gòu)造函數(shù)返回一個字符串:
typeof?String("str");?//?->?'string'
String("str");?//?->?'str'
String("str")?==?"str";?//?->?true
我們來試試一個 new:
new?String("str")?==?"str";?//?->?true
typeof?new?String("str");?//?->?'object'
對象?那是什么?
new?String("str");?//?->?[String:?'str']
點(diǎn)擊下方“技術(shù)漫談”,選擇“設(shè)為星標(biāo)”注:部分內(nèi)容參考自jsisweird
第一時間關(guān)注技術(shù)干貨!
