使用`this`调用函数内部函数的问题

Rya*_*fer 2 javascript this self

window.onerror = function(e){alert(e)};
function main(){
    this.work = [];
    this.start_working = function() {
        try{
            if(this.work.length > 0){
                var y = this.work.shift();
                y.func(y.args);
            }
        }
        catch(e){alert(e)};
    };
    this.add_work = function(f, a){
        this.work.push({func:f, args:a});
    };
    this.foo = function(){
        function footoo(){alert("bar");}
        this.add_work(footoo);
    };
    this.foothree = function(){
        this.add_work(this.foo);
    };
    this.start = function(){
        setInterval(function(){this.start_working();}.bind(this), 1);
    };
};
x = new main();
x.start();
x.foothree();
Run Code Online (Sandbox Code Playgroud)

这是我在其他地方用来顺序运行动画的函数的淡化版本.

预期行为:

this.foothree通过间隔添加foo来处理间隔.this.foo然后处理添加footoo到最后处理的间隔警告"bar".

问题:

this.foothree被处理时,一个错误被抛出:

TypeError:this.add_work不是函数.


为什么我不使用更简单的东西:

基本上我需要一个函数,它允许我将更复杂的动画组成更简单的动画到要处理的队列,这样我就可以重用那个动画了.Foothree在这个例子中,只是模拟一个将真实动画添加footoo到要处理的队列的调用.Footoo将由更简单的动画组成foo,它将按顺序执行.

mor*_*els 5

this返回[[ThisValue]]的财产EnvironmentRecordLexicalEnvironmentExecutionContext运行功能(参见规范).

它的值取决于函数的调用方式.如果你打电话

this.foo = function(){
    function footoo(){alert("bar");}
    this.add_work(footoo);
};
Run Code Online (Sandbox Code Playgroud)

在声明的函数中没有add_work方法.

你应该采用var _self = this;pattern来指出正确的调用上下文.

基本上代码应该重写如下:

function main(){
    var _self = this;

    this.work = [];
    this.start_working = function() {
        try{
            if(_self.work.length > 0){
                var y = _self.work.shift();
                y.func(y.args);
            }
        }
        catch(e){alert(e)};
    };
    this.add_work = function(f, a){
        _self.work.push({func:f, args:a});
    };
    this.foo = function(){
        function footoo(){alert("bar");}
        _self.add_work(footoo);
    };
    this.foothree = function(){
        _self.add_work(_self.foo);
    };
    this.start = function(){
        setInterval(function(){_self.start_working();}, 1);
    };
};
Run Code Online (Sandbox Code Playgroud)

编辑:

.bind(this)从原始代码中删除.