从onload事件调用对象函数会使其丢失上下文

Hea*_*rab 2 javascript html5 prototype object onload

我想在加载所有需要的图像时调用一个函数.图像的数量是预先知道的,所以我尝试将函数调用附加到每个图像的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>
Run Code Online (Sandbox Code Playgroud)

当它刚刚从对象的另一个函数调用时(参见#1),它就像我预期的那样工作.但是,当从onload事件调用它时(参见#2),变量变为"未定义"或"NaN"等.发生了什么?我究竟做错了什么?我如何使其工作?

我不记得曾经在Javascript中创建自己的对象,所以我当然对这个"我的代码有什么问题"这个问题深表歉意.我主要使用本文作为参考,第1.2节.

为了以防万一,我在http://jsfiddle.net/ffJLn/上放了相同的代码

Ben*_*Lee 7

bind 回调的上下文:

this.img1.onload = this.loading_complete.bind(this);
Run Code Online (Sandbox Code Playgroud)

请参阅: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() };
Run Code Online (Sandbox Code Playgroud)

闭包是保持对其上下文的引用的函数(事实上,javascript中的所有函数都以这种方式工作).所以在这里你要创建一个匿名函数来保持对它的引用self.所以这是维持背景和loading_complete拥有权利的另一种方式this.

请参阅:http://jsfiddle.net/ffJLn/2/(与您的相同,但有第二种可能性)