我遇到与闭包相关的代码问题,我需要一些帮助。
正如你所看到的,我在for循环中创建了几个图像,我正在分配不同的id(即数组中的数字)。到现在为止还挺好。当我点击不同的图像时,我希望以图像id作为参数调用函数showId,但问题是用作函数参数的数字总是变为nr 8(数组中的最后一个数字)。我该如何解决这个问题?
提前致谢。
var imageArea = document.getElementById('imageArea');
var nrArray = [1,2,3,4,5,6,7,8];
for (var i = 0; i < nrArray.length; i++){
var image = document.createElement('img');
image.src = "images/theimage.png";
image.id = nrArray[i];
imgArea.appendChild(image);
image.addEventListener ('click',function() {showId(image.id);},false);
}
答案 0 :(得分:3)
只需使用this
关键字重新引用父对象即可访问ID:
//In this case, this refers to the object that owns the function, i.e., your img
image.addEventListener ('click',function() {showId(this.id);},false);
答案 1 :(得分:3)
这个完全相同的问题在stackoverflow上有很多答案,我会在一分钟内找到一些,但这里有关键点:
function
var image = ...
不在您认为的位置。只有一个image
变量,(由于词法作用域)是你在闭包中访问的变量,它在循环结束时显然会指向最后一个迭代项。例如:
(function(localImage) {
image.addEventListener ('click',function() {showId(localImage.id);},false);
})(image);
另外,正如其他人所指出的那样,事件监听器闭包是在它们被绑定的 context 中执行的。相反,在不担心使用近距离修复范围的情况下,您可以这样做:
image.addEventListener ('click',function() {showId(this.id);},false);
修改的
关于答案的类似问题和一些不同观点的一些链接:
我可以继续,但是数字很多......
答案 2 :(得分:1)
为什么不使用this
?
var imgArea = document.getElementById('imageArea');
var nrArray = [1,2,3,4,5,6,7,8];
for (var i = 0; i < nrArray.length; i++) {
var image = document.createElement('img');
image.src = "images/theimage.png";
image.id = nrArray[i];
imgArea.appendChild(image);
image.addEventListener('click', function() {
showId(this.id);
}, false);
}
另外,您的原始问题是关于创建闭包,所以尽管我确信使用this
将提供您现在所需的内容,但我将添加一些创建示例一个新的范围,允许您利用闭包来完成相同的任务:
var imgArea = document.getElementById("imageArea");
var nrArray = [1, 2, 3, 4, 5, 6, 7, 8];
for (var i = 0; i < nrArray.length; i++) {
createClosure(i);
}
function createClosure(i) {
var image = document.createElement('img');
image.src = "images/theimage.png";
image.id = nrArray[i];
imgArea.appendChild(image);
image.addEventListener('click', function () {
showId(image.id);
}, false);
}
jsFiddle演示:http://jsfiddle.net/HMYsW/1/
答案 3 :(得分:0)
this
的属性),您将再次遇到相同的问题。
要解决此问题,请创建一个新的闭包(即function
):
function createListener(id) {
return function() { showId(id); }
}
var imageArea = document.getElementById('imageArea');
for (var i = 1; i <= 8; i++){
var image = document.createElement('img');
image.src = "images/theimage.png";
image.id = i;
imgArea.appendChild(image);
image.addEventListener ('click', createListener(image.id), false);
}
这里我有一个创建并返回另一个函数的函数。返回的函数将是实际的事件侦听器。在创建过程中,变量id
将被关闭并保持其值。当然,你可以一步到位:
image.addEventListener ('click', function (id) {
return function() { showId(id); };
}(image.id), false);
答案 4 :(得分:0)
一旦代码超出范围,Javascript就不会自动从内存中删除变量。这意味着即使您在特定范围内声明变量,在您的情况下也是for循环,在此之外变量仍然存在。
附加到您所有图片的事件监听器正在执行第$showId(image.id);
行
但是因为变量没有从内存中删除,变量image
仍然存在,即for循环中的最后一个变量。这就是为什么你总是得到数组中的最后一个数字:8。
当调用eventlistener时,它将变量this
设置为自己的元素,因此将变量从image更改为this将解决问题。
addEventListener调用变为:
image.addEventListener ('click',function() {showId(image.id);},false);