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

时间:2019-05-19 22:14:05

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

然后,我希望能够像这样调用Foo的方法:

foo = new Foo();
var func = foo.funcs[1];
func();

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

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

2 个答案:

答案 0 :(得分:7)

您的问题是这一行:

var func = foo.funcs[1];

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

值得您花时间阅读讨论this的{​​{3}}。学习应该少于一个小时,而且一旦学习,您将领先于大多数JS程序员。

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

  

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

     

有新电话吗?使用新构造的对象。

     

通过通话还是申请(或绑定)通话?使用指定的对象。

     

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

     

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

基于上述规则,下面的代码是使代码按您期望的方式工作的最简单方法:

'use strict';

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

Foo.prototype.func1 = function() {
  this.prop = 1;
  console.log('called func1. this.prop =', this.prop);
}

Foo.prototype.func2 = function() {
  this.prop = 2;
  console.log('called func2. this.prop =', this.prop);
}


const foo = new Foo();
foo.funcs[1]();

答案 1 :(得分:6)

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

这可以通过将this传递到每个函数的bind()来完成:

this.func1.bind(this)

以这种方式使用bind()可确保将thisfunc1的{​​{1}}定义为func2的实例。反过来,这可以确保可以按预期访问和分配Foo()

this.prop

要注意的另一项关键是上面的基于'use strict'; function Foo() { this.funcs = { /* Bind the functions to this Foo() instance */ 1: this.func1.bind(this), 2: this.func2.bind(this), } } Foo.prototype.func1 = function() { this.prop = 1; console.log('called func1. this.prop =', this.prop); } Foo.prototype.func2 = function() { this.prop = 2; console.log('called func2. this.prop =', this.prop); } const foo = new Foo(); var func = foo.funcs[1]; func(); foo.funcs[2]();的方法,可以确保,如果您获取并调用了对bind()字段中的一个函数的引用(如原始帖子中所示),将按预期工作:

funcs

在不使用/* As per original post - doing this is not possible without .bind() */ var func = foo.funcs[1]; func(); 的情况下,由于bind()未绑定到func的实例,因此获取和调用func的方法将失败。