我遇到一个我无法解决的问题。我不知道这是缺乏知识还是Java语言中甚至不可能做到这一点,但我希望了解这一点。
我试图在对象中执行功能别名列表。在执行这些功能时,我想像直接从实例本身执行它们一样使用它们,因此我可以在该调用的方法中使用其他方法和实例变量。为了使我的解释更加清楚,这是一个示例:
class Bar {
constructor() {
this.name = "Bar";
}
someMethod() {
console.log(this.name) // should log Bar
}
}
class Foo {
constructor() {
this.name = "Foo";
}
someOtherMethod() {
console.log(this.name) // should log Foo
}
}
const bar = new Bar();
const foo = new Foo();
const methodList = {
foo: bar.someMethod,
baz: foo.someOtherMethod,
}
for(let prop in methodList) {
methodList[prop](); // logs 2x undefined
}
for(let prop in methodList) {
methodList[prop].apply(foo); //logs 2x Foo
}
从上面的示例中可以看出,this.name
是类实例中的变量。执行第二个循环时,将按预期应用上下文并正确记录日志。我想看到该上下文是自动应用的,因为函数别名对象是在另一个文件中执行的,不知道foo
或bar
而是仅接收列表。
有什么办法可以做到这一点?
答案 0 :(得分:2)
您可以将foo
和bar
方法包装在它们自己的函数中。在这些方法中,您可以像下面这样在对象上调用对象的方法someMethod()
/ someOtherMethod()
:
const methodList = {
foo: (...args) => bar.someMethod(...args),
baz: (...args) => foo.someOtherMethod(...args),
}
当前,您的第一个循环不起作用,因为您的this
并未引用对象的实际上下文,因为这不是用于调用该方法的内容。相反,它指的是您的methodList
请参见下面的示例:
class Bar {
constructor() {
this.name = "Bar";
}
someMethod() {
console.log(this.name) // should log Bar
}
}
class Foo {
constructor() {
this.name = "Foo";
}
someOtherMethod() {
console.log(this.name) // should log Foo
}
}
const bar = new Bar();
const foo = new Foo();
const methodList = {
foo: (...args) => bar.someMethod(...args),
baz: (...args) => foo.someOtherMethod(...args),
}
for(let prop in methodList) {
methodList[prop](); // correct logs
}
答案 1 :(得分:1)
之所以会这样,是因为调用this
时上下文methodList[prop]
是methodList
,因此this
中的someMethod
和someOtherMethod
实际上是:
{
foo: bar.someMethod,
baz: foo.someOtherMethod,
}
要解决此问题,您可以将方法包装在返回调用的方法的匿名函数中,如下所示:
class Bar {
constructor() {
this.name = "Bar";
}
someMethod(a,b,c) {
console.log(a,b,c,this.name) // should log Bar
}
}
class Foo {
constructor() {
this.name = "Foo";
}
someOtherMethod(a,b,c) {
console.log(a,b,c,this.name) // should log Foo
}
}
const bar = new Bar();
const foo = new Foo();
const methodList = {
foo: (...args) => bar.someMethod(...args), // <-- anonymous function that, once invoked, returns `bar.someMethod()`, hence the contextual `this` of someMethod will be `bar`.
baz: function() { // <-- same as above, just written without the lambda notation.
return foo.someOtherMethod(...arguments);
}//^
}// | <-- that evaluation is actually calling the above code block.
// |-------------------------------------|
for(let prop in methodList) {// |
methodList[prop](1,4,'hello'); // <------|
}