为了避免误解,让我们先就某些词的意思达成一致。以下的含义不是普遍接受的,我只是建议它们作为这个问题的背景。
Function的一个实例。它有一个与之相关的程序。在JavaScript中,通常使用属性和方法自定义对象,而函数不定制。换句话说,如果在代码中看到这一点:
foo.bar // Accessing a property on an instance
foo.baz() // Calling a method on an instance那么foo几乎肯定是一个对象,而不是一个函数。
但从技术上讲,函数与对象并没有什么不同(实际上,JS中的函数被认为是对象,我只是为了清楚地区分它们)。
如果你这么做
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...it会很好的工作。
我想再介绍两个术语,这样你才能理解我的意思。我不是想在这里改变JavaScript的规则,我只是想被理解。
许多JS库提供函数对象,例如jQuery和LoDash。也就是说,你可以同时做$()和$.map()。
好了,现在谈一谈。
我希望能够创建具有以下要求的自己的函数对象:
class声明来描述函数对象的类。或者至少描述类的方式应该是足够方便的。将属性和方法强制分配给函数是不方便的。console.log(this.foo)的普通方法,那么分配给myFunctionObject.foo应该同时修改主mehtod和另一个方法的行为。换句话说,我希望能够做到这一点:
class Foo {
constructor () { this.bar = 'Bar'; }
mainMethod () { console.log(this.bar); }
anotherMethod () { console.log(this.bar); }
}...but -- Foo的一个实例--应该可以将foo.mainMethod()简单地作为foo()使用。
执行foo.bar = 'Quux'应该同时修改foo()和foo.anotherMethod()的行为。
也许有一种方法可以用class Foo extends Function来实现
发布于 2015-10-11 16:23:03
如果不覆盖任何内容,new Foo将返回对象类型,而不是函数类型。你有可能做到
class Foo {
constructor(){
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将返回一个显式设置的函数,以便返回一个具有正确原型链配置的函数。请注意,我正在显式地设置foo.bar而不是this.bar,以便hasOwnProperty在整个代码中仍能按预期工作。
您也可以通过基类设置它来解决这个问题。
class CallableClass {
constructor(callback){
const fn = (...args) => callback(...args);
Object.setPrototypeOf(fn, this);
return fn;
}
}
class Foo extends CallableClass {
constructor(){
super(() => this.mainMethod());
this.bar = 'Bar';
}
mainMethod () { console.log(this.bar); }
anotherMethod () { console.log(this.bar); }
}我是用真正的ES6编写这篇文章的,但是如果您想让它在Node v4中工作,就必须将其余的/扩展的args更改为正常的函数。例如:
const foo = function(){ callback.apply(undefined, arguments); };这两种方法的缺点是它们依赖于Object.setPrototypeOf,这在IE<=10中不起作用,因此它将取决于您需要什么支持。一般的理解是,Object.setPrototypeOf也非常慢,所以我不确定您在这里有很多选择。
ES6为这种情况提供的主要选择是代理,但它们还没有得到很好的支持。
发布于 2015-10-11 23:17:48
AFAIK无法将[Call]方法添加到现有对象中。
代理可能看起来是一个潜在的解决方案,但问题是代理对象与[ProxyHandler]是不同的对象,并且是 trap。
因此,唯一可行的解决方案是使用所需的[Call]创建一个新函数,替换它的[Prototype],并使构造函数返回该函数而不是“the”实例。
class Foo {
constructor () {
var instance = function(){ return instance.mainMethod(); };
Object.setPrototypeOf(instance, Foo.prototype);
return Object.assign(instance, {bar: 'Bar'});
}
mainMethod () { console.log(this.bar); }
anotherMethod () { console.log(this.bar); }
}https://stackoverflow.com/questions/33064625
复制相似问题