我是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。
这是什么问题,有没有更好的方法来实现呢?
您的问题是这一行:
var func = foo.funcs[1];
Run Code Online (Sandbox Code Playgroud)
JavaScript this根据函数的调用方式确定的值。如果使用点表示法,例如,foo.funcs[1]();则this与foo对象关联的will 的值。但是,当您运行时func(),这只是一个简单的函数,this其默认值为undefined。
这将是值得你花时间阅读你不知道JS的两章是讨论this。学习应该少于一个小时,而且一旦学习,您将领先于大多数JS程序员。
在您阅读本章之前,这些规则可能没有意义,但下面总结了这些规则:
确定
this执行功能的绑定要求找到该功能的直接调用位置。一旦检查,就可以按照以下优先顺序将四个规则应用于呼叫站点:叫新的?使用新构造的对象。
随叫随到还是申请(或绑定)?使用指定的对象。
用拥有该调用的上下文对象调用?使用该上下文对象。
默认值:在严格模式下未定义,否则为全局对象。
根据上述规则,以下代码是使代码按预期运行的最简单方法:
var func = foo.funcs[1];
Run Code Online (Sandbox Code Playgroud)
有几种方法可以实现所需的功能,但是最可靠的方法是将bind()每个函数实例Foo()化为实例。
这可以通过传递this给bind()每个函数来完成:
this.func1.bind(this)
Run Code Online (Sandbox Code Playgroud)
bind()以这种方式使用可确保将thisfor func1和for func2定义为的实例Foo()。反过来,这确保this.prop可以按预期访问和分配:
this.func1.bind(this)
Run Code Online (Sandbox Code Playgroud)
另一个需要注意的关键是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。