我是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
。
这里有什么问题,有没有更好的方法来实现呢?
答案 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()
可确保将this
和func1
的{{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
的方法将失败。