javascriptでイベントを循環的に追加する場合のクローズド問題解決

2192 ワード

これは経典の問題です.一時期純jsを書きませんでした.最近はいつも以前転んだ穴に落ちています.今回は半日かけて登りました.だから記録してください.
 
昨日jsコードを書きましたが、カスタムdivに登録したonclickイベントで発見された値は常にサイクルの最後の層の値です.
最初のコード:
 
for(var i in array){
	var rowDiv = document.createElement("div");
	rowDiv.innerText = array[i]["name"];
	rowDiv.onclick = function(){//      
		pNode = this.parentNode;
		pNode.previousSibling.value = this.innerText;//   div       
		if(onclickCallback){//            
			onclickCallback(array[i]);
		}
	};
}
 
読む視線を邪魔しないように、この問題に関係のないコードを直接切ってください.
 
for(var i in array){
	var rowDiv = document.createElement("div");
	rowDiv.innerText =array[i];
	rowDiv.onclick = function(){//      
		alert(array[i]);
	};
}
 
ここで一つのdivをクリックしてalertが出るのは最後のサイクルの値です.この現象はすぐに思い出します.これは古典的なクローズド問題です.Oclickのイベントを実行する時に外部関数にアラー[i]の定義を探します.ここでiはforサイクルを実行した後、array[array.length-1]になりました.
 
インターネットで検索してみましたが、改善の方法はたくさんあります.
方法1は、外層が匿名関数を包含し、各循環のインデックス結果を入力として入力し、自己実行する.
 
for(var i in array){
	(function(obj){
		var rowDiv = document.createElement("div");
		rowDiv.innerText = obj;
		rowDiv.onclick = function(){//      
			alert(obj);
		};
	})(array[i]);
}
 
方法2は、同様にクローズドを利用して、innerTextに値を付ける部分は問題ありません.問題があるのはクローズド特性を使ったオンリーイベントの登録部分だけです.
 
for(var i in array){
	var rowDiv = document.createElement("div");
	rowDiv.innerText = array[i];
	rowDiv.onclick = (function(obj){//      
		return function(){
			alert(obj);
		};
	})(array[i]);
}
 
方法3は、上記の解決方法は難しそうですが、クローズドの中でうろうろしています.個人的には、クローズドしなくてもいいと思います.他の解法を以下に示します.
for(var i in array){
	var rowDiv = document.createElement("div");
	rowDiv.innerText = array[i];
	rowDiv.obj = array[i];
	rowDiv.onclick = function(){//      
		alert(this.obj);
	};
}
これは個人的には良いと思いますが、domオブジェクトにカスタム属性を追加して値を保存します.divのイベントがトリガされた時にはthisで参照できます.