下面整理了一些在前端技術中極易犯錯的知識點。
js部分
題目來源:
- JavaScript Puzzlers! do you really know JavaScript?
一、數據類型
1. 整數的安全範圍?
var END = Math.pow(2, 53);
var START = END - 100;
var count = 0;
for (var i = START; i <= END; i++) {
count++;
}
console.log(count);
0
100
101
other
解答:
按正常的思考,count 爲 101 無疑。然而這可是 JavaScript Puzzlers! 中的題目,do you really know JavaScript?
這個題目考察對 Number 存儲方式的掌握。在《Javascript权威指南 第六版》3.1小节中有如下描述:
Javascript 中所有數字均用浮點數值表示。Javascript 採用 IEEE 754 標準定義的64位浮點數格式表示數字。
按照 Javascript 中的數字格式,能夠表示的整數範圍是從 − 2 53 -2 ^ {53} −253 ~ 2 53 2^{53} 253,包含邊界值。如果使用了超過此範圍的整數,則無法保證低位數字的精度。然而需要注意的是,Javascript 中實際的操作(比如數組索引,以及第4章講到的位操作符)則是基於32位整數。
在瀏覽器控制檯中測試如下:
Number.MAX_SAFE_INTEGER // 9007199254740991
Number.MIN_SAFE_INTEGER // -9007199254740991
Math.pow(2, 53) // 9007199254740992
Math.pow(2, 53) + 1 // 9007199254740992
Math.pow(2, 53) + 2 // 9007199254740994
末尾兩行的結果出乎意料,倒數第二行導致本題出現死循環,答案是 other。可見在 MAX_SAFE_INTEGER 之外的計算確實不安全。
如果將 for 循環中的增量改爲 i += 2
,結果是多少呢?
沒想到這又是對的,51
。所以這個題目不用 i += 2
,哈。
那麼爲什麼是 2 53 2^{53} 253 呢?
引用 Js的整型你懂了嗎:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gXKUItvS-1593586058323)(https://sfault-image.b0.upaiyun.com/389/752/3897521971-550a765b3fdf2_articlex)]
使用 52 位表示一个数的整数部分,那么最大可以精确表示的数应该是 2 52 − 1 2^{52}-1 252−1才对, 就像 64 位表示整数时那样: 2 63 − 1 2^{63} - 1 263−1 (去掉 1 位符号位)。 但其实浮点数在保存数字的时候做了规格化处理,以 10 进制为例:
20*10^2 => 2*10^3 //小数点前只需要保留 1 位数
对于二进制来说, 小数点前保留一位, 规格化后始终是
1.***
, 节省了 1 bit,这个 1 并不需要保存。
2. 自動轉爲String
var lowerCaseOnly = /^[a-z]+$/;
[lowerCaseOnly.test(null), lowerCaseOnly.test()] // [true, true]
the argument is converted to a string with the abstract
ToString
operation, so it is"null"
and"undefined"
.
3. 不可 delete 特性
var a = 1;
delete a;
typeof a; // "number"
typeof a
結果是?
a = 1;
delete a;
typeof a; // "undefined"
typeof a
結果又是什麼?
eval("var a = 1")
delete a;
typeof a; // "undefined"
這次 typeof a
結果呢?
解答:
上述 3 題只有第一行的賦值語句不同。本題考察對可刪除特性 的理解。
未声明的赋值在一个全局对象上创建一个可删除的属性
中間一題是未聲明的賦值,所以是可刪除的。
在Eval中创建的变量或方法比较特别,没有DontDelete特性,也就是说可以删除
故第 3 題也是可以刪除的。
二、函數
1. map與parseInt?
["1", "2", "3"].map(parseInt)
["1", "2", "3"]
[1, 2, 3]
[0, 1, 2]
other
解答:
該題考察了對 map 和 parseInt 函數的掌握情況。
["1", "2", "3"].map(function () {
console.log(arguments)
})
在控制檯中看看輸出了什麼?
原來 map 傳遞了3個參數給裏面的函數,分別爲 item, index, array。也就是說 parseInt 實際上會收到3個參數,以數組中的 “2” 爲例,parseInt 實際調用爲 parseInt("2", 1, ["1", "2", "3"])
。
parseInt 的調用方式爲 parseInt (val, radix)
。 將 2 用 1 進制表示,結果是什麼呢? 我們得到 NaN, 故結果爲 [“1”, NaN, NaN],答案是 other
。
2. replace 與 parseInt
"1 2 3".replace(/\d/g, parseInt)
解答:
"1 2 3".replace(/\d/g, () => console.log(arguments))
看看 replace 往函數里裝了什麼?
["1", 0, "1 2 3"]
["2", 2, "1 2 3"]
["3", 4, "1 2 3"]
依次爲 elem, position, array
故,結果爲 “1 NaN 3”
3. 計算parseInt表達式結果
parseInt(3, 8)
parseInt(3, 2)
parseInt(3, 0)
3, 3, 3
3, 3, NaN
3, NaN, NaN
other
解答:
本題繼續考察對 parseInt 的掌握。
parseInt(3, 2)
, 在2進制中不存在3,故爲 NaN。
parseInt(3, 0)
,當第二個參數爲 0 時,parseInt 會忽略該參數,使用默認的 10 進制。故結果爲 3, NaN, 3
, 答案爲 other
。
4. map 函數
var ary = Array(3);
a