嘗試解析js面試題(二)


說明:一共有13題(原本14題,最后一道什么鬼,嫌棄不要了),覆蓋面比較廣,都屬於比較燒腦的類型,各種神坑;不過對於夯實js理論基礎幫助非常大;看看都能做對幾題吧(🙈😏)

//第1題 (function () { return typeof arguments; })(); A. "object" B. "array" C. "arguments" D. "undefined" //第2題 var f = function g() { return 23; }; typeof g(); A. "number" B. "undefined" C. "function" D. Eorror //第3題 (function (x) { delete x; return x; })(1); A. 1 B. null C. undefined D. Error //第4題 var y = 1, x = y = typeof x; x; A. 1 B. "number" C. undefined D. "undefined" //第5題 (function f(f) { return typeof f(); })(function () { return 1; }); A. "number" B. "undefined" C. "function" D. Error //第6題 var foo = { bar: function () { return this.baz; }, baz: 1 }; (function () { return typeof arguments[0](); })(foo.bar); A. "undefined" B. "object" C. "number" D. "function" //第7題 var foo = { bar: function () { return this.baz; }, baz: 1 }; typeof (f = foo.bar)(); A. "undefined" B. "object" C. "number" D. "function" //第8題 var f = (function f() { return "1"; }, function g() { return 2; })(); typeof f; A. "string" B. "number" C. "function" D. "undefined" //第9題 var x = 1; if (function f() {}) { x += typeof f; } x; A. 1 B. "1function" C. "1undefined" D. NaN //第10題 var x = [typeof x, typeof y][1]; typeof typeof x; A. "number" B. "string" C. "undefined" D. "object" //第11題 (function (foo) { return typeof foo.bar; })({ foo: { bar: 1 } }); A、“undefined” B、“object” C、“number” D、Error //第12題 (function f() { function f() { return 1; } return f(); function f() { return 2; } })(); A、1 B、2 C、Error (e.g. “Too much recursion”) D、undefined //第13題 function f() { return f; } new f() instanceof f; A、true B、false //第14題 with (function(x, undefined){}) length; A、1 B、2 C、undefined D、Error

解析

ps1:這套題在知乎上也有相關的解析可以參考如何理解這14道JavaScript 題--知乎

//第1題 答案A (function () { return typeof arguments; })(); A. "object" B. "array" C. "arguments" D. "undefined"

arguments是函數免費贈送的一個關鍵字,功能類似數組,但實際上是一個對象,因此這題答案是A

//舉個arguments的例子 function foo(x) { alert(x); // 10 for (var i=0; i<arguments.length; i++) { alert(arguments[i]); // 10, 20, 30 } } foo(10, 20, 30);

//第2題 答案D var f = function g() { return 23; }; typeof g(); A. "number" B. "undefined" C. "function" D. Eorror

1)函數定義有兩種方式,一種是普通函數直接聲明function a () {return b;};(這種在解析時會被優先處理)

2)另外一種就是匿名函數 var a = function () {returnb;};,這種也被稱為表達式類型,因為右邊部分已經成為一個表達式的一部分,無法再被正常訪問

3)題目中的情況按照第二種方法理解,作為表達式的g函數已經無法被訪問

4)注意,題目是typeof g(),不是typeof g;這兩者的區別在於函數調用"()"的運算優先級高於typeof,所以先解析g()的情況下,js直接報錯,而不是給出"undefiend";因此答案是D

//調試比對結果 //typeof a是function這個沒有問題 //typeof fn1是得到undefined //typeof fn1()是錯誤報警形式出現 var a = function fn1 (){} typeof a //"function" typeof fn1() //Uncaught ReferenceError: fn1 is not defined(…) typeof fn1 //"undefined"

//第3題 答案A (function (x) { delete x; return x; })(1); A. 1 B. null C. undefined D. Error

1)delete是用來刪除對象的屬性的,它不能夠刪除函數中傳遞的參數

2)所以這里delete x這句其實並沒有什么軟用,函數正常執行傳參及返回參數;因此答案是A

//給個delete使用方法的舉例 var xiaoming = { name: '小明' }; xiaoming.age; // undefined xiaoming.age = 18; // 新增一個age屬性 xiaoming.age; // 18 delete xiaoming.age; // 刪除age屬性 xiaoming.age; // undefined delete xiaoming['name']; // 刪除name屬性 xiaoming.name; // undefined delete xiaoming.school; // 刪除一個不存在的school屬性也不會報錯

//第4題 答案D var y = 1, x = y = typeof x; x; A. 1 B. "number" C. undefined D. "undefined"

1)賦值運算符由右向左運算

2)首先typeof x因為x未聲明,因此結果是"undifined"(注意:typeof的結果都是以字符串形式給出的)

3)接着"undifined"被接連賦值給y與x,所以答案是D


//第5題 答案A (function f(f) { return typeof f(); })(function () { return 1; }); A. "number" B. "undefined" C. "function" D. Error

1)這道題可以拆分一下,首先是函數本體

//此處是一個函數,傳入了一個叫f的參數,這個參數還是另外一個函數 //隨后在本體函數內部,將這個參數所代表的函數執行了一下,並返回其typeof結果 (function f(f) { return typeof f(); //這里的f是指參數函數 })();

2)其次是參數

function () { return 1; }

3)所以現在就很清晰了,按照運算符優先級,首先參數函數執行f()結果為1;typeof 1結果為"number";所以結果是A


//第6題 答案A var foo = { bar: function () { return this.baz; }, baz: 1 }; (function () { return typeof arguments[0](); })(foo.bar); A. "undefined" B. "object" C. "number" D. "function"

1)先說下我的理解,這題考的是this的指向問題

2)this指向的四種情況,其中只有作為方法調用或者apply/call強行指向的情況下才可能指向原函數

3)在作為普通函數調用的時候是指向window的,所以這里的argument[0]()的調用形式我認為是這種調用

4)也就是說this.baz就是window.baz,當然是"undefined",所以答案是A

this對我來說還是比較繞的一個東西,就再貼上別人的解析看看吧

這個分析總的結果就是foo.bar中的this指向的是arguments(此處懵逼臉😳)

為什么是"undefined"?.
我們必須要知道this運算符是怎么工作的.

JS語言精粹總結的很精煉:
1 純粹的函數調用
2 作為對象方法的調用
3 作為構造函數調用
4 apply調用

我們看看題目是屬於那種環境?
arguments[0]()中執行了一個方法,arguments[0]就是foo.bar方法
注意:這在foo.bar中的this是沒有綁定到foo

雖然 foo.bar 傳遞給了函數,但是真正執行的時候,函數 bar 的上下文環境是 arguments ,並不是 foo

arguemnts[0] 可以理解為 arguments.0(不過寫代碼就不要這樣了,語法會錯誤的),所以這樣看來,上下文環境是 arguemnts 就沒問題了,所以在執行baz的時候自然this就是window了,window 上沒有baz屬性,返回的就是undefined, typeof調用的話就轉換成"undefined"了


//第7題 答案A var foo = { bar: function () { return this.baz; }, baz: 1 }; typeof (f = foo.bar)(); A. "undefined" B. "object" C. "number" D. "function"

1)這題還是在考察this的指向問題

2)foo.bar的確是方法的調用方式,但是在賦值給f的時候這個this的指向還是被改變了

3)把調用函數拆分一下就清楚了

var f = foo.bar typeof f();

4)這樣在調用形式上又是普通函數調用,this指向window;同上題,答案是A


//第8題 答案B var f = (function f() { return "1"; }, function g() { return 2; })(); typeof f; A. "string" B. "number" C. "function" D. "undefined"

1)此處是一個立即執行函數,但是在前面的包含函數的圓括號(命名空間)中出現了2個函數,並用逗號分隔

2)這種形式,最終圓括號返回的是最后的一個值

//來看一個例子 var a = (1,2,3,4) console.log(a) //4 //題目中的情況,最終將后面的函數返回 var f = (function f() {return "1";}, function g() {return 2;}) console.log(f) //function g() {return 2;}

3)所以,同樣的此處會返回第二個函數出來執行,得到的最終返回值是2並賦值給f;所以答案是B


//第9題 答案C var x = 1; if (function f() {}) { x += typeof f; } x; A. 1 B. "1function" C. "1undefined" D. NaN

1)首先在if判定中,函數f的布爾值是true;所以判定條件成立,可以執行if中的語句

2)函數f在正常聲明的情況下,typeof f應該是"function"

3)但是題目中f函數只是if的判定條件,沒有經過聲明;所以typeof f返回"undefined",所以答案是C

//單獨聲明的情況下,f是函數類型 function f(){} typeof f //"function" //但題目中f作為一個if中的判定條件存在,未得到聲明 if(function f(){}){ } typeof f //"undefined"

//第10題  答案B
var x = [typeof x, typeof y][1]; typeof typeof x; A. "number" B. "string" C. "undefined" D. "object"

1)數組中獲取坐標1的是typeof y,因為y未聲明,所以返回"undefined"並賦值給x

2)所以typeof x就是typeof "undefined"返回"string",typeof "string"依然返回"string";所以答案是B


//第11題 答案A (function (foo) { return typeof foo.bar; })({ foo: { bar: 1 } }); A、"undefined" B、"object" C、"number" D、Error

1)又是一個立即執行的匿名函數,首先拆分一下

var a = { foo:{ bar:1 } } (function (foo) { return typeof foo.bar; })(a);

2)再簡化

var a = { foo:{ bar:1 } } var foo = a; typeof foo.bar

3)再簡化,用a將foo替代掉

var a = { foo:{ bar:1 } } typeof a.bar

現在就清楚了,無法直接通過a訪問bar屬性,只有通過a.foo.bar才成立,所以答案是A

ps:這個思路是看到的別人的解析,但是總覺得簡化函數的第二步存在問題(var foo = a這步)

//第12題 答案B (function f() { function f() { return 1; } return f(); function f() { return 2; } })(); A、1 B、2 C、Error (e.g. “Too much recursion”) D、undefined

1)形式類似於第8題,中間多了個return

2)正常來說,return會導致跳出函數,所以后邊的語句不會執行

3)但是,此處因為兩個函數都是普通聲明的函數,會被優先解析,所以第二個函數是在return前執行的;所以答案還是B


//第13題 答案B function f() { return f; } new f() instanceof f; A、true B、false

1)首先,instanceof是用來檢測原型的,如果是原型返回true,否則返回false

2)此處函數f中return了一個返回值f,導致new出來的東西與原來期望的實例化對象已經不是一個東西了,所以答案是false

//如果這里返回的是this或者不定義返回值(默認返回一個this) function f() { return this; } new f() instanceof f; //true //題目中return了f后的結果 function f() { return f; } new f() instanceof f; //false

3)再說的詳細一些,引用一篇看到的解釋:小小滄海--第六問處對於new的解釋

1、沒有返回值則按照其他語言一樣返回實例化對象。

2、若有返回值則檢查其返回值是否為引用類型。如果是非引用類型,如基本類型(string,number,boolean,null,undefined)則與無返回值相同,實際返回其實例化對象。

3、若返回值是引用類型,則實際返回值為這個引用類型。

//對比調試 //首先沒有返回值,沒有問題 function a(){} new a() //a {} new a() instanceof a //true //這是返回非引用類型,也是true function a(){return true} new a() //a {} new a() instanceof a //true //這是返回引用類型,這個就是false了,因為new出來的東西被返回值覆蓋 function a(){return {a:1}} new a() //Object {a: 1} new a() instanceof a //false //類似的,題目中應該也是引用的類型 function f() {return f;} new f() //function f(){return f} //關鍵就是這里了 //new出來的東西被返回值強行指向原本的函數本身,而不是其實例化對象,當然原型也無從談起 new f() instanceof f; //false

也就是說,調試結果顯示;只有new出來的是原函數的實例化對象,這個原型才會指向原函數(這是我的理解😳)

媽蛋總算寫完,累死寶寶了😂

新手上路,錯漏之處,請各位大神指導



文/小pxu(簡書作者)
原文鏈接:http://www.jianshu.com/p/55e54345829a
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM