我想在加载所有需要的图像时调用函数。图像的数量是预先知道的,所以我尝试将函数调用附加到每个图像的onload事件并计算它被调用的次数。
<html>
<head>
<script>
var tractor;
function Tractor()
{
this.init_graphics();
}
Tractor.prototype.init_graphics = function()
{
this.gr_max = 3;
this.load_count = 0;
this.loading_complete(); // #1 test call, works OK
this.img1 = new Image();
this.img1.onload = this.loading_complete; // #2 gets called, but gr_max = undefined, load_count = NaN
this.img1.src = "http://dl.dropbox.com/u/217824/tmp/rearwheel.gif"; //just a test image
}
Tractor.prototype.loading_complete = function()
{
this.load_count += 1;
alert("this.loading_complete, load_count = " + this.load_count + ", gr_max = " + this.gr_max);
if(this.load_count >= this.gr_max) {this.proceed();}
};
function start()
{
tractor = new Tractor();
}
</script>
</head>
<body onload="start();">
</body>
</html>
当它刚从对象的另一个函数调用时(参见#1),它就像我预期的那样工作。但是,当从onload事件调用它时(参见#2),变量变为“未定义”或“NaN”等。发生了什么?我究竟做错了什么?我如何使它工作?
我不记得曾经在Javascript中创建自己的对象,所以我当然对这个“我的代码有什么问题”这个问题深表歉意。我主要使用this article作为参考,第1.2节。
以防万一,我在http://jsfiddle.net/ffJLn/
上添加了相同的代码答案 0 :(得分:7)
bind
回调的上下文:
this.img1.onload = this.loading_complete.bind(this);
请参阅:http://jsfiddle.net/ffJLn/1/(与您的相同,但添加此内容)
以下是对bind
详细工作方式的解释:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
基本思想是它使绑定函数中的this
等于你传递给bind
的参数。
另一个选择是创建一个闭包:
var self = this;
this.img1.onload = function() { self.loading_complete() };
闭包是保持对其上下文的引用的函数(事实上,javascript中的所有函数都以这种方式工作)。所以在这里你要创建一个匿名函数来保持对self
的引用。因此,这是维护上下文的另一种方式,loading_complete
拥有正确的this
。
请参阅:http://jsfiddle.net/ffJLn/2/(与您的相同,但有第二种可能性)
答案 1 :(得分:2)
当#2被调用时,您的this
已发生变化。 this
现在指的是new Image()
而不是Tractor
对象。
尝试更改......
this.img1.onload = this.loading_complete;
到
var that = this;
this.img1.onload = function() { that.loading_complete(); };
答案 2 :(得分:0)
您现在可以使用provide lexical binding的es6箭头功能:
this.img1.onload = () => { this.loading_complete(); };