所有其他答案都是“创建闭包”的某个版本。好的,这行得通。我认为闭包很酷,支持它们的语言也很酷...
但是:在我看来,有一种更简洁的方法可以实现这一点。只需使用图像对象存储所需内容,并通过"this
"在加载处理程序中访问它即可:
imageObj = new Image();
imageObj.x = 1;
imageObj.y = 2;
imageObj.onload = function() {
context.drawImage(this, this.x, this.y);
};
imageObj.src = ".....";
这是一种非常通用的技术,我经常在DOM中的许多对象中使用它。(特别是当我有四个按钮并希望它们都共享一个“onclick”处理程序时,我会使处理程序从按钮中提取一些自定义数据来执行该按钮的特定操作。)
一个警告:你必须小心,不要使用对象具有特殊含义或用途的属性。(例如:你不能为任何老的自定义用途使用imageObj.src
;你必须将其留给源URL。)但是,在一般情况下,你怎么知道一个特定对象如何使用其所有属性呢?严格来说,你无法知道。因此,为了尽可能地使这种方法安全:
- 将所有自定义数据打包到单个对象中
- 将该对象分配给一个不寻常或不太可能被对象本身使用的属性。
在这方面,“x”和“y”的使用有些冒险,因为某些浏览器中的JavaScript实现可能在处理图像对象时使用这些属性。但这可能是安全的:
imageObj = new Image();
imageObj.myCustomData = {x: 1, y: 2};
imageObj.onload = function() {
context.drawImage(this, this.myCustomData.x, this.myCustomData.y);
};
imageObj.src = ".....";
这种方法的另一个优点是:如果您正在创建大量给定对象,它可以节省很多内存,因为您现在可以共享一个onload处理程序的单个实例。考虑一下,使用闭包:
for (var i=0; i<1000; i++) {
var imageObj = new Image();
var x = i*20;
var y = i*10;
imageObj.onload = function() {
context.drawImage(imageObj, x, y);
};
imageObj.src = ".....";
}
相较于共享加载函数,将您的自定义数据藏在图像对象中:
function myImageOnload () {
context.drawImage(this, this.myCustomData.x, this.myCustomData.y);
}
for (var i=0; i<1000; i++) {
imageObj = new Image();
imageObj.myCustomData = {x: i*20, y: i*10};
imageObj.onload = myImageOnload;
imageObj.src = ".....";
}
由于不需要创建所有这些匿名函数,因此可以节省很多内存并且可能运行速度更快。 (在这个示例中,onload函数是一行代码....但我有100行的onload函数,1000个它们肯定被认为是没有好理由浪费很多内存。)
更新:请参见使用"data-*"属性进行标准(和“标准批准”)方法,代替我临时建议使用myCustomData
。
var
声明在闭包内部给它们一个范围。(如果变量是函数的形式参数,则会隐式发生这种情况,这就是为什么基于闭包的答案“有效”的原因。) - Dan H