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

Problems with calling function inside function using `this`

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();

这是我在别处使用的函数的简化版本,可以按顺序 运行 动画。

预期行为:

this.foothree是由区间加foo处理的。然后处理 this.foo,将 footoo 添加到最终处理警报 "bar".

的间隔

问题:

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

TypeError: this.add_work is not a function.


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

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

thisreturns[[ThisValue]]EnvironmentRecordLexicalEnvironmentExecutionContext属性运行 函数(参见 the spec)。

其值取决于how the function is called。如果你打电话

this.foo = function(){
    function footoo(){alert("bar");}
    this.add_work(footoo);
};

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

您应该采用 var _self = this; 模式以指向正确的调用上下文。

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

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);
    };
};

编辑:

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

这个问题有两个组成部分。

首先是关于 JavaScript 中的 this 的问题,也就是函数的 "target" 或 "receiver"。

JavaScript 中函数的目标取决于您是否处于严格模式、调用函数的方式以及是否使用 bind 绑定。

假设采用严格模式(您应该始终将 'use strict'; 放在 JavaScript 的顶部):

foo(); // this inside foo will be undefined

a.foo(); // this inside foo will be a

a.foo.call(o); // this inside foo will be o

a.foo.apply(o); // this inside foo will be o

a.foo.bind(o)(); // this inside foo will be o

这个问题的第二个方面是作者试图做什么。我很确定他引入链动画的复杂性是不必要的,他应该使用 requestAnimationFrame,但讨论这个需要另一个问题。

示例:

function foo() {
    document.write('foo', this, '<br/>');
    bar();
}


function bar() {
    document.write('bar', this, '<br/>');
}

foo();
document.write('------<br/>');
foo.call({});