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

时间:2016-07-12 14:45:07

标签: 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();

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

预期行为:

this.foothree由间隔添加foo处理。然后处理this.foo,将footoo添加到最后处理的区间,警告“bar”。

问题:

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

  

TypeError:this.add_work不是函数。

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

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

2 个答案:

答案 0 :(得分:5)

this会返回正在运行的函数的[[ThisValue]] EnvironmentRecord的{​​{1}}属性(请参阅the spec)。

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

LexicalEnvironment

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

您应该采用var this.foo = function(){ function footoo(){alert("bar");} this.add_work(footoo); }; 模式来指出正确的调用上下文。

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

add_work

修改

从原始代码中删除_self = this;

答案 1 :(得分:1)

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

首先,它是关于JavaScript中的this的问题,也就是" target"或"接收器"功能。

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({});
&#13;
&#13;
&#13;