前面兩篇文章介紹了上下文、做用域、閉包、this。這裏我精心挑選了一些特別經典的面試題(不按期更新,跪求收藏)。相信經過這些題目能讓你徹底通關JS三座大三中的之一。javascript
這類題目仍是挺簡單的,我總結了幾個要注意的地方
1.有沒有閉包
2.若是有閉包,看建立了幾個閉包。換句話說,是在一個閉包內直接操做仍是操做完一個閉包,再建立一個新的閉包繼續操做
3.注意數據的歸屬,即數據存放在哪一個上下文環境
java
var n=0; function a(){ var n=10; function b(){ n++; console.log(n); } b(); return b; } var c=a(); c(); console.log(n); //11 12 0
var a=9; function fn(){ a=0; //若是這裏是var a = 0 ,答案是多少 return function(b){ return b+a++; } } var f=fn(); console.log(f(5)); console.log(fn()(5)); console.log(f(5)); console.log(a); // 5 5 6 2 // 若是是var a = 5 5 6 9
var ary=[1,2,3,4]; function fn(ary){ ary[0]=0; ary=[0]; ary[0]=100; return ary; } var res=fn(ary); console.log(ary); console.log(res); // [0,2,3,4] [100]
function fn(i) { return function (n) { console.log(n + (i++)); } } var f = fn(10); f(20); fn(20)(40); fn(30)(50); f(30); //30 60 80 41
var i = 10; function fn() { return function (n) { console.log(n + (++i)); } } var f = fn(); f(20); fn()(20); fn()(30); f(30); //31 32 43 44
請問以下代碼是否能實現?
若是不能實現那麼如今的效果是什麼樣的?
應該作怎樣的修改才能達到咱們想要的效果,並說明原理?es6
<div id="btnBox"> <input type="button" value="button_1" /> <input type="button" value="button_2" /> <input type="button" value="button_3" /> <input type="button" value="button_4" /> <input type="button" value="button_5" /> </div> <script type="text/javascript"> var btnBox=document.getElementById('btnBox'), inputs=btnBox.getElementsByTagName('input'); var l=inputs.length; for(var i=0;i<l;i++){ inputs[i].onclick=function(){ alert(i); } } </script>
1.不能實現
2.由於js沒有塊做用域,因此公用的外層做用域的i,當點擊觸發函數的時候 ,應當注意外層的i是5了,因此所有打印5沒毛病
3.
解決思路1:沒有塊做用域我就用es6的let造成塊做用域面試
for(let i=0;i<l;i++){ inputs[i].onclick=function(){ alert(i); } }
解決思路2:每次綁定的時候i其實都是正確的,我能不能用另一個變量將每次的i存起來呢?閉包
//這樣行嗎? for(var i=0;i<l;i++){ inputs[i].onclick=function(){ var num = i alert(num); } } //這樣仍是不行,由於回調函數定義的時候並不會執行,因此當var num = i 執行的時候i已經等於5了
那麼我應該讓回調函數定義的時候裏面的代碼能當即執行,接收到參數0,1,2,3,4函數
for(var i=0;i<l;i++){ inputs[i].onclick=(function(){ var num = i alert(num); })(i) } //這樣也有問題i傳遞進去了,可是裏面核心代碼定義也執行了,我想讓它點擊的時候再執行
for(var i=0;i<l;i++){ inputs[i].onclick=(function(){ var num = i return function (e) { //注意這個時候e是啥,是點擊的事件 console.log(num) } })(i) } //這樣就沒毛病了,返回一個方法,不會當即執行,i傳進去了,給了num,因爲有閉包,又不會被銷燬
還能怎麼優化?既然i能傳進去,我爲啥還要而外用個變量保存呢?優化
for(var i=0;i<l;i++){ inputs[i].onclick=(function(x){//x是形參,因爲閉包存在,上下文不銷燬 return function () { console.log(x) } })(i) }
這類題目嚴格按上篇文章的分析思路,不復雜,就是麻煩一點。不要在腦子裏想,每步的結果用紙和筆演算下
this
var num = 10; var obj = {num: 20}; obj.fn = (function (num) { this.num = num * 3; num++; return function (n) { this.num += n; num++; console.log(num); } })(obj.num); var fn = obj.fn; fn(5); obj.fn(10); console.log(num, obj.num); //22 23 65 30