js常見面試題

// 有5個li標籤
var items = document.querySelectorAll('li');

for (var i = 0; i < items.length; i++) {
items[i].onclick = function(){
console.log(i);
};
}
分析上面代碼,依次點擊li會輸出什麼?
答案:不管點擊哪個li,都輸出5
分析之前,需要明確的幾個知識點:

首先,牢記:js中只有全局作用域和函數作用域
其次:牢記:變量的生命週期,分爲三種情況,
對於全局變量而言,當頁面被刷新或被關閉時,它就死了,也就是其所佔的內存被釋放;
對於函數內的局部變量(不考慮閉包),退出函數時,它就死了,也就是其佔用的內存被釋放;
對於函數內的局部變量(考慮閉包),當被返回的函數引用了局部變量,則只有引用該返回函數的變量被回收,局部變量纔會被回收。
分析代碼:

var i 是全局變量
當for循環中給每個li添加了onclick的事件處理函數,注意:事件處理函數並未運行,所以當for執行完畢後,其實i並未被釋放,i的值爲5
當點擊每個li時,調用的i還是原來那個i,也就是5, 所以不管點擊哪個li,都打印出5
代碼2
function outerFn() {
console.log("Outer function");
function innerFn() {
var innerVar = 0;
innerVar++;
console.log("Inner function\t");
console.log("innerVar = "+innerVar+"");
}
return innerFn;
}

var fnRef = outerFn();
fnRef();
fnRef();

以上代碼都輸出:1
因爲函數作用域的關係,每調用依次fnRef(),都將生成新的innverVar

改進

function outerFn() {
var outerVar = 0;
console.log("Outer function");
function innerFn() {
outerVar++;
console.log("Inner function\t");
console.log("outerVar = " + outerVar + "");
}
return innerFn;
}

var fnRef = outerFn();
fnRef();
fnRef();

var fnRef2 = outerFn();
fnRef2();
fnRef2();
輸出: 1, 2,1, 2
var fnRef = outerFn(); 生成了outerVar變量,每次調用fnRef()時,獲取的還是原來的那個outerVar;
var fnRef2 = outerFn(); 生成了另一個outerVar變量,這個變量與fnRef中的是不同的,因爲它們處於不同的作用域

再次改進

function outerFn() {
var outerVar = 0;
function innerFn1() {
outerVar++;
console.log( outerVar);
}

function innerFn2() {
    outerVar += 2;
    console.log(outerVar);
}
return { "fn1": innerFn1, "fn2": innerFn2 };

}

var fnRef = outerFn();
fnRef.fn1();
fnRef.fn2();
fnRef.fn1();
輸出: 1, 3, 4
當調用var fnRef = outerFn() 時,可以理解爲“創建了一個屬於fnRef執行環境”,之後訪問的fnRef.fn1(); fnRef.fn2();均是在該執行環境下執行的

回到代碼1,如何修改代碼,能夠實現點擊li,打印出正確的數字呢?只需要爲每一個li,創造出屬於他們自己的獨立的i,這個i與for循環中的i,是不同的i,也就是爲每個li創造一個獨立的執行環境,在js中只有通過函數能夠創造一個獨立的執行環境(也可以說是作用域),這時候,需要用到閉包來實現,代碼如下:

var items = document.querySelectorAll('li');
for (var i = 0; i < items.length; i++) {
items[i].onclick = (function(i){
return function(){
console.log(i);
};
})(i);
}
龍華大道1號http://www.kinghill.cn/LongHuaDaDao1Hao/index.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章