面試官總結:44個 Javascript 變態題解析(上)
當初筆者做這套題的時候不僅懷疑智商, 連人生都開始懷疑了....
不過, 對於基礎知識的理解是深入編程的前提. 讓我們一起來看看這些變態題到底變態不變態吧!
第1題
["1", "2", "3"].map(parseInt)
知識點:
Array/map
Number/parseInt
Global_Objects/parseInt
JavaScript parseInt
首先, map接受兩個參數, 一個回調函數 callback, 一個回調函數的this值
其中回調函數接受三個參數 currentValue, index, arrary;
而題目中, map只傳入了回調函數--parseInt.
其次, parseInt 只接受兩個兩個參數 string, radix(基數).
在沒有指定基數,或者基數為 0 的情況下,JavaScript 作如下處理:
如果字符串 string 以"0x"或者"0X"開頭, 則基數是16 (16進制).
如果字符串 string 以"0"開頭, 基數是8(八進制)或者10(十進制),那麼具體是哪個基數由實現環境決- 定。ECMAScript 5 規定使用10,但是並不是所有的瀏覽器都遵循這個規定。因此,永遠都要明確給出radix參數的值。
如果字符串 string 以其它任何值開頭,則基數是10 (十進制)。
所以本題即問
parseInt('1', 0);
首先後兩者參數不合法.
所以答案是 [1, NaN, NaN]
第2題
[typeof null, null instanceof Object]
兩個知識點:
Operators/typeof
Operators/instanceof
Operators/instanceof(中)
typeof 返回一個表示類型的字符串.
instanceof 運算符用來檢測 constructor.prototype 是否存在於參數 object 的原型鏈上.
這個題可以直接看鏈接... 因為 typeof null === 'object'
自語言之初就是這樣....
typeof 的結果請看下錶:
type result
所以答案 [object, false]
第3題
[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]
知識點:
Array/Reduce
arr.reduce(callback[, initialValue])
reduce接受兩個參數, 一個回調, 一個初始值.
回調函數接受四個參數 previousValue, currentValue, currentIndex, array
需要注意的是 If the array is empty and no initialValue was provided, TypeError would be thrown.
所以第二個表達式會報異常. 第一個表達式等價於 Math.pow(3, 2) => 9; Math.pow(9, 1) =>9
答案 an error
第4題
var val = 'smtg';
兩個知識點:
Operators/Operator_Precedence
Operators/Conditional_Operator
簡而言之 +
的優先級 大於 ?
所以原題等價於 'Value is true' ? 'Somthing' : 'Nonthing'
而不是 'Value is' + (true ? 'Something' : 'Nonthing')
答案 'Something'
第5題
var name = 'World!';
這個相對簡單, 一個知識點:
Hoisting
在 JavaScript中, functions 和 variables 會被提升。變量提升是JavaScript將聲明移至作用域 scope (全局域或者當前函數作用域) 頂部的行為。
這個題目相當於
var name = 'World!';
所以答案是 'Goodbye Jack'
第6題
var END = Math.pow(2, 53);
一個知識點:
Infinity
在 JS 裡, Math.pow(2, 53) == 9007199254740992 是可以表示的最大值. 最大值加一還是最大值. 所以循環不會停.
補充: @jelly7723
js中可以表示的最大整數不是2的53次方,而是1.7976931348623157e+308。
2的53次方不是js能表示的最大整數而應該是能正確計算且不失精度的最大整數,可以參見js權威指南。
9007199254740992 +1還是 9007199254740992 ,這就是因為精度問題,如果 9007199254740992 +11或者 9007199254740992 +111的話,值是會發生改變的,只是這時候計算的結果不是正確的值,就是因為精度丟失的問題。
第7題
var ary = [0,1,2];
答案是 []
看一篇文章理解稀疏數組
譯 JavaScript中的稀疏數組與密集數組
Array/filter
我們來看一下 Array.prototype.filter 的 polyfill:
if (!Array.prototype.filter) {
我們看到在迭代這個數組的時候, 首先檢查了這個索引值是不是數組的一個屬性, 那麼我們測試一下.
0 in ary; => true
也就是說 從 3 - 9 都是沒有初始化的'坑'!, 這些索引並不存在與數組中. 在 array 的函數調用的時候是會跳過這些'坑'的.
第8題
var two = 0.2
JavaScript的設計缺陷?浮點運算:0.1 + 0.2 != 0.3
IEEE 754標準中的浮點數並不能精確地表達小數
那什麼時候精準, 什麼時候不經準呢? 筆者也不知道...
答案 [true, false]
第9題
function showCase(value) {
兩個知識點:
Statements/switch
String
switch 是嚴格比較, String 實例和 字符串不一樣.
var s_prim = 'foo';
答案是 'Do not know!'
第10題
function showCase2(value) {
解釋:
String(x) does not create an object but does return a string, i.e. typeof String(1) === "string"
還是剛才的知識點, 只不過 String 不僅是個構造函數 直接調用返回一個字符串哦.
答案 'Case A'
第11題
function isOdd(num) {
一個知識點
Arithmetic_Operators#Remainder
此題等價於
7 % 2 => 1
需要注意的是 餘數的正負號隨第一個操作數.
答案 [true, true, true, false, false]
第12題
parseInt(3, 8)
第一個題講過了, 答案 3, NaN, 3
第13題
Array.isArray( Array.prototype )
一個知識點:
Array/prototype
一個鮮為人知的實事: Array.prototype => []
;
---> 對JS原型的一些思考 by renaesop
答案: true
第14題
var a = [0];
JavaScript-Equality-Table
更新通過一張簡單的圖,讓你徹底地、永久地搞懂JS的==運算 非常不錯的一篇文章!
解析:
Boolean([0]) === true
[0] == true
true 轉換為數字 => 1
[0] 轉化為數字失敗, 轉化為字符串 '0', 轉化成數字 => 0
0 !== 1
答案: false
第15題
[]==[]
[] 是Object, 兩個 Object 不相等
答案是 false
第16題
'5' + 3
兩個知識點:
Arithmetic_Operators#Addition
Arithmetic_Operators#Subtraction
+
用來表示兩個數的和或者字符串拼接, -
表示兩數之差.
請看例子, 體會區別:
> '5' + 3
也就是說 -
會盡可能的將兩個操作數變成數字, 而 +
如果兩邊不都是數字, 那麼就是字符串拼接.
答案是 '53', 2
第17題
1 + - + + + - + 1
這裡應該是(倒著看)
1 + (a) => 2
所以答案 2
第18題
var ary = Array(3);
稀疏數組. 同第7題.
題目中的數組其實是一個長度為3, 但是沒有內容的數組, array 上的操作會跳過這些未初始化的'坑'.
所以答案是 ["1", undefined × 2]
這裡貼上 Array.prototype.map 的 polyfill.
Array.prototype.map = function(callback, thisArg) {
第19題
function sidEffecting(ary) {
這是一個大坑, 尤其是涉及到 ES6語法的時候
知識點:
Functions/arguments
首先 The arguments object is an Array-like object corresponding to the arguments passed to a function.
也就是說 arguments
是一個 object
, c 就是 arguments[2], 所以對於 c 的修改就是對 arguments[2] 的修改.
所以答案是 21
.
然而!!!!!!
當函數參數涉及到 any rest parameters, any default parameters or any destructured parameters
的時候, 這個 arguments 就不在是一個 mapped arguments object
了.....
請看:
function sidEffecting(ary) {
答案是 12
!!!!
請讀者細細體會!!
第20題
var a = 111111111111111110000,
答案還是 111111111111111110000
. 解釋是 Lack of precision for numbers in JavaScript affects both small and big numbers.
但是筆者不是很明白................ 請讀者賜教!
第21題
var x = [].reverse;
這個題有意思!
知識點:
Array/reverse
The reverse method transposes the elements of the calling array object in place, mutating the array, and returning a reference to the array.
也就是說 最後會返回這個調用者(this), 可是 x 執行的時候是上下文是全局. 那麼最後返回的是 window
.
補充:
@stellar91 這個筆者實踐了一下 發現 firefox 是 window, chrome 報錯
VM190:2 Uncaught TypeError: Array.prototype.reverse called on null or undefined(…)
可能是實現不同, 在 chrome 中應該是對調用者做了檢查.
答案是 window
第22題
Number.MIN_VALUE > 0
true
@10081677wc
MIN_VALUE 屬性是 JavaScript 中可表示的最小的數(接近 0 ,但不是負數),它的近似值為 5 x 10-324。
今天先到這裡, 下次我們來看後22個題!
最後在對各位剛剛入門前端的程序員提點建議。
對於剛剛參加工作的同學來說,思考比做事更重要。如果你為了業務而業務,不停的去堆積,只能說過些年你還是如此。去好好的想一想,編程到底是在做什麼?
如果你現在還準備去學習前端 ,那我只能說你的視野都被狗吃了。至少你可以通過社區來了解前端的發展動態,去了解出現了哪些新的框架,更新了哪些新的Api或者屬性。未來一段時間內,國內或者國際廠商會使用哪些技術等等。
分享之前我還是要推薦下我自己的前端學習群:180442230,不管你是小白還是大牛,小編我都挺歡迎,不定期分享乾貨,包括我自己整理的一份2017最新的前端資料和零基礎入門教程,送給大家,歡迎初學和進階中的小夥伴