JavaScript:调用存储在变量中的函数时访问“ this”

Pet*_*ter 13 javascript

我是JavaScript新手,所以这可能是一个琐碎的问题:

我正在尝试构造一个对象,该对象存储从一组整数到其某些方法的映射,即像这样的东西:

'use strict';

function Foo() {
    this.funcs = {
        1: this.func1,
        2: this.func2,
    }
}

Foo.prototype.func1 = function() {
    this.prop = 1;
}

Foo.prototype.func2 = function() {
    this.prop = 2;
}
Run Code Online (Sandbox Code Playgroud)

然后,我希望能够调用如下方法Foo

foo = new Foo();
var func = foo.funcs[1];
func();
Run Code Online (Sandbox Code Playgroud)

但这导致:Cannot set property 'prop' of undefined,即this不引用foo

这是什么问题,有没有更好的方法来实现呢?

Tod*_*fee 7

您的问题是这一行:

var func = foo.funcs[1];
Run Code Online (Sandbox Code Playgroud)

JavaScript this根据函数的调用方式确定的值。如果使用点表示法,例如,foo.funcs[1]();thisfoo对象关联的will 的值。但是,当您运行时func(),这只是一个简单的函数,this其默认值为undefined

这将是值得你花时间阅读你不知道JS的两章是讨论this。学习应该少于一个小时,而且一旦学习,您将领先于大多数JS程序员。

在您阅读本章之前,这些规则可能没有意义,但下面总结了这些规则:

确定this执行功能的绑定要求找到该功能的直接调用位置。一旦检查,就可以按照以下优先顺序将四个规则应用于呼叫站点:

叫新的?使用新构造的对象。

随叫随到还是申请(或绑定)?使用指定的对象。

用拥有该调用的上下文对象调用?使用该上下文对象。

默认值:在严格模式下未定义,否则为全局对象。

根据上述规则,以下代码是使代码按预期运行的最简单方法:

var func = foo.funcs[1];
Run Code Online (Sandbox Code Playgroud)


Dac*_*nny 6

有几种方法可以实现所需的功能,但是最可靠的方法是将bind()每个函数实例Foo()化为实例。

这可以通过传递thisbind()每个函数来完成:

this.func1.bind(this)
Run Code Online (Sandbox Code Playgroud)

bind()以这种方式使用可确保将thisfor func1和for func2定义为的实例Foo()。反过来,这确保this.prop可以按预期访问和分配:

另一个需要注意的关键是bind()上面的基于方法,该方法可以确保,如果您获取并调用了对funcs原始帖子中所示的字段中的一个函数的引用,则它将按预期工作:

/* As per original post - doing this is not possible without .bind() */
var func = foo.funcs[1];
func();
Run Code Online (Sandbox Code Playgroud)

如果不使用bind(),则此获取和调用方法func将由于func未绑定到的实例而失败Foo