瞭解閉包
js閉包問題說到底就是js的作用域問題,而作用域在js中也就是局部變量和全部變量。局部變量是指只能在本變量聲明的函數內部調用。全局變量時整個代碼中都可以調用的變量。
eg1:
var aa = 10;
function fun(){
var bb = 20;
console(aa);
console(bb);
}
fun();
上段代碼中,aa即爲全局變量,bb爲局部變量。
什麼是閉包?
閉包就是能夠讀取其他函數內部變量的函數。由於在javascript中,只有函數內部的子函數才能讀取局部變量,所以說,閉包可以簡單理解成“定義在一個函數內部的函數“。
所以,在本質上,閉包是將函數內部和函數外部連接起來的橋樑。
我遇到的閉包問題
先看這樣一段代碼。
for (var ii = 0; ii < 5; ii++) {
items[ii].addTouchEventListener(function (sender, eventType) {
if (eventType === ccui.Widget.TOUCH_ENDED) {
if (self.curState === 0) {
self.curState = 1;
self.back_btn.setVisible(true);
self.return_btn.setVisible(false);
self.record_scroll.setVisible(false);
self.record_item_panel.setVisible(true);
UICommonWidget.update_scroll_items(self.record_item_scroll, recordList[ii]["round_result"], update_item_func);
}
}
});
}
當這段代碼執行完畢之後,你會發現update_scroll_items方法只調用了items最後一個元素的數據,而不是理想中調用的items0 - items4,這就是因爲update_scroll_items
函數在for循環內部的一個函數裏面,他調用的ii每次都只調用了等於4的數據,這就是因爲閉包的原因。
那麼怎麼解決這個問題呢,在JavaScript ES6 裏面有一個let申明變量關鍵字,我們只需要在for循環內部另外申明一個全局變量就可以了。修改代碼如下:
for (var ii = 0; ii < 5; ii++) {
let i = ii;
items[i].addTouchEventListener(function (sender, eventType) {
if (eventType === ccui.Widget.TOUCH_ENDED) {
if (self.curState === 0) {
self.curState = 1;
self.back_btn.setVisible(true);
self.return_btn.setVisible(false);
self.record_scroll.setVisible(false);
self.record_item_panel.setVisible(true);
UICommonWidget.update_scroll_items(self.record_item_scroll, recordList[i]["round_result"], update_item_func);
}
}
});
}
這樣就能達到我們想要的效果了。
以上看法僅屬於個人觀點,如有不正之處,望各位大大海涵,並私信錯誤之處。