gpt4 book ai didi

javascript - 使 `obj.someMethod()` 可用作 `obj()`,而不阻止 `obj` 表现为正常实例

转载 作者:行者123 更新时间:2023-11-28 18:58:39 29 4
gpt4 key购买 nike

为了避免误解,我们首先要就某些词语的含义达成一致。以下含义并非普遍接受的含义,我仅建议将它们作为此问题的背景。

  • function -- Function 的一个实例。它有一个与其关联的过程
  • object——任何其他类的实例。没有与之相关的程序。
  • 过程——可以执行的代码块。在JS程序中只能找到与函数相关的内容。
  • 方法——存储在另一个对象的属性中的函数。方法在其宿主对象的上下文中执行。

在 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

...它会工作得很好。

我想再介绍两个术语,以便您能明白我的意思。我并不是想在这里改变 JavaScript 的规则,只是想被理解。

  • 函数对象 -- 用作对象函数:拥有自己的属性和/或方法。
  • 主方法——函数对象本身的过程,而不是作为函数对象上的属性存储的方法。

许多 JS 库提供函数对象,例如 jQuery 和 LoDash。 IE。您可以同时执行 $()$.map()

<小时/>

好了,现在说正事。

我希望能够创建自己的函数对象,并满足以下要求:

  1. 我应该能够使用 ES2015 class 声明来描述我的函数对象的类。或者至少描述类的方式应该足够方便。强制将属性和方法分配给函数并不方便。
  2. 我的函数对象主方法应该与其其他方法在相同的上下文中执行。
  3. 主方法和其他方法应绑定(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()foo.anotherMethod() 的行为。

也许有一种方法可以通过class Foo extends Function来实现它?

最佳答案

如果您不重写任何内容,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 将返回一个已显式设置的函数,以便它返回一个具有正确原型(prototype)链配置的函数。请注意,我明确设置了 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 中工作,则必须将其余/扩展参数更改为普通函数。例如

const foo = function(){ callback.apply(undefined, arguments); };

这两种方法的缺点是它们依赖于 Object.setPrototypeOf,它在 IE<=10 中不起作用,因此这取决于您需要什么支持。一般的理解是 Object.setPrototypeOf 也非常慢,所以我不确定这里有很多选择。

ES6 针对这种情况提供的主要替代方案是代理,但它们尚未得到很好的支持。

关于javascript - 使 `obj.someMethod()` 可用作 `obj()`,而不阻止 `obj` 表现为正常实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33064625/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com