为了避免误解,我们首先要就某些词语的含义达成一致。以下含义并非普遍接受的含义,我仅建议将它们作为此问题的背景。
- function --
Function
的一个实例。它有一个与其关联的过程.
- object——任何其他类的实例。没有与之相关的程序。
- 过程——可以执行的代码块。在JS程序中只能找到与函数相关的内容。
- 方法——存储在另一个对象的属性中的函数。方法在其宿主对象的上下文中执行。
在 JavaScript 中,sự vật通常是使用属性和方法自定义的,而函数则不然。换句话说,如果您在代码中看到以下内容:
foo.bar // Accessing a property on an instance
foo.baz() // Calling a method on an instance
那么 foo
几乎肯定是一个sự vật, thay vì函数.
但从技术上讲函数Vàsự vật没有什么不同(事实上,JS中的函数被认为是sự vật>,这只是我为了清楚起见区分它们)。
如果你这样做:
const foo = function () { /*...*/ }
foo() // Calling the function's procedure
foo.bar // Accessing a property on the function
foo.baz() // Calling a method on the function
...它会工作得很好。
我想再介绍两个术语,以便您能明白我的意思。我并不是想在这里改变 JavaScript 的规则,只是想被理解。
- 函数对象 -- 用作sự vậtcủa函数:拥有自己的属性和/或方法。
- 主方法——函数对象本身的过程,而不是作为函数对象上的属性存储的方法。
许多 JS 库提供函数对象,例如 jQuery 和 LoDash。 IE。您可以同时执行 $()
Và $.map()
.
好了,现在说正事。
我希望能够创建自己的函数对象,并满足以下要求:
- 我应该能够使用 ES2015
class
声明来描述我的函数对象的类。或者至少描述类的方式应该足够方便。强制将属性和方法分配给函数并不方便。
- 我的函数对象của主方法应该与其其他方法在相同的上下文中执行。
- 主方法和其他方法应绑定(bind)到同一个实例。例如,如果我有一个 main 方法 和一个普通的方法,它们都执行
console.log(this.foo)
,然后分配给 myFunctionObject.foo
应该修改主方法和其他方法的行为。
换句话说,我希望能够做到这一点:
class Foo {
constructor () { this.bar = 'Bar'; }
mainMethod () { console.log(this.bar); }
anotherMethod () { console.log(this.bar); }
}
...但是 Foo
的实例应该具有 foo.mainMethod()
,可以简单地用作 foo()
.
执行 foo.bar = 'Quux'
应该修改 foo()
Và foo.anotherMethod()
的行为。
也许有一种方法可以通过class Foo extends Function
来实现它?
如果您不重写任何内容,new Foo
将返回对象类型,而不是函数类型。你可以这样做
class Foo {
người xây dựng(){
const foo = () => foo.mainMethod();
Object.setPrototypeOf(foo, this);
foo.bar = 'Bar';
return foo;
}
mainMethod () { console.log(this.bar); }
anotherMethod () { console.log(this.bar); }
}
这样 new Foo
将返回一个已显式设置的函数,以便它返回一个具有正确原型(prototype)链配置的函数。请注意,我明确设置了 foo.bar
thay vì this.bar
,以便 hasOwnProperty
在整个代码中仍然按预期工作。
您还可以通过基类进行设置来解决此问题,例如
class CallableClass {
constructor(callback){
const fn = (...args) => callback(...args);
Object.setPrototypeOf(fn, this);
return fn;
}
}
class Foo extends CallableClass {
người xây dựng(){
super(() => this.mainMethod());
this.bar = 'Bar';
}
mainMethod () { console.log(this.bar); }
anotherMethod () { console.log(this.bar); }
}
我正在真正的 ES6 中编写此代码,但如果您希望它在 Node v4 中工作,则必须将其余/扩展参数更改为普通函数。例如
const foo = function(){ callback.apply(undefined, arguments); };
这两种方法的缺点是它们依赖于 Object.setPrototypeOf
,它在 IE<=10 中不起作用,因此这取决于您需要什么支持。一般的理解是 Object.setPrototypeOf
也非常慢,所以我不确定这里有很多选择。
ES6 针对这种情况提供的主要替代方案是代理,但它们尚未得到很好的支持。
Tôi là một lập trình viên xuất sắc, rất giỏi!