鍍金池/ 問答/Java  HTML/ 這是js閉包問題嗎?

這是js閉包問題嗎?

圖片描述

回答
編輯回答
乞許

因為你每次for循環(huán)的時候,給按鈕添加了點擊事件,同時btn也會指向不同的按鈕,在最后一次循環(huán)的時候,btn指向了最后一個按鈕,所以每次輸出的都是4

2017年2月10日 19:34
編輯回答
脾氣硬

或許你可以把里面的點擊事件包成匿名函數(shù)自執(zhí)行然后傳參,也可以應用ES6里面的let 聲明循環(huán)變量,因為在每一個{}中都是一個let作用域

2017年7月17日 03:40
編輯回答
咕嚕嚕

題主的 for 循環(huán)跑完后,實際上:

i=5
btn = 最后一個 input

為什么這樣呢,我們來看下代碼,稍微改了下:

for(var i=0;i<5;i++){
    var btn=document.createElement('input');
    btn.setAttribute('type','button');
    btn.setAttribute('value','btn'+i);
    document.body.insertBefore(btn,document.body.firstElementChild); //直接插入到文檔最前面,方便測試
    btn.onclick=function(){
        alert(btn.value);
    };
}

要知道 es6 之前是沒有塊級作用域的,且

用 var 定義的變量會有一個聲明提升的特性,這個動作開始于代碼執(zhí)行之前,會將 var 定義的變量提升到所在函數(shù)或全局環(huán)境的頂端,但是賦值操作仍然停留在原地

題主的代碼其實相當于:

var i,btn;
for(i=0;i<5;i++){
    btn=document.createElement('input');
    btn.setAttribute('type','button');
    btn.setAttribute('value','btn'+i);
    document.body.insertBefore(btn,document.body.firstElementChild);
    btn.onclick=function(){
        alert(btn.value);
    };
}
console.log(btn); // btn 被賦值了5次,覆蓋了4次,最后一個是 btn4,所以很顯然是最后一個
console.log(i);  // i=5的時候跳出循環(huán),所以 i 最后一個值是 5

這樣是不是就很好理解了?

因為你給 btn 綁定的事件處理程序(回調函數(shù))并不是馬上執(zhí)行,觸發(fā)的時候才執(zhí)行,這個時候 btn 已經被覆蓋了4次,變成最后一個 btn 了;

核心原因是: var 有聲明提前的特性。如要改的話,有多種方式,這里暫就說兩種:
法一:btn 改為 this (推薦)

for(var i=0;i<5;i++){
    var btn=document.createElement('input');
    btn.setAttribute('type','button');
    btn.setAttribute('value','btn'+i);
    document.body.insertBefore(btn,document.body.firstElementChild);
    btn.onclick=function(){
        alert(this.value);
    };
}

在事件綁定中,如果事件處理程序(也就是回調函數(shù))中沒有嵌套的函數(shù),事件綁定在誰身上,this 就指向誰,如果回調里還有嵌套函數(shù),this 默認指向全局對象,所以這里 this 就指向了綁定時的那個 btn;不明白戳這
法二:用 let 代替 var

for(var i=0;i<5;i++){
    let btn=document.createElement('input');
    btn.setAttribute('type','button');
    btn.setAttribute('value','btn'+i);
    document.body.insertBefore(btn,document.body.firstElementChild);
    btn.onclick=function(){
        alert(btn.value);
    };
}

這是 ES6 的內容,詳細理解戳這:深入理解ES6-中

2017年2月5日 13:17
編輯回答
執(zhí)念
this.value; // 試試
2017年11月9日 15:15