【问题标题】:Are there efficient ways to use `__proto__` or `setPrototypeOf()` in javascript?有没有在 javascript 中使用 `__proto__` 或 `setPrototypeOf()` 的有效方法?
【发布时间】:2017-09-29 00:38:49
【问题描述】:

MDN 对修改代码中的原型有一个巨大的可怕警告:

改变对象的[[Prototype]] 现代 JavaScript 引擎优化属性访问,非常慢 每个浏览器和 JavaScript 引擎中的操作。对的影响 改变继承的表现是微妙而广泛的,并且是 不仅限于在Object.setPrototypeOf(...) 语句中花费的时间, 但可以扩展到任何可以访问任何对象的代码 [[Prototype]] 已更改。如果你关心性能,你 应避免设置对象的[[Prototype]]。相反,创建一个 具有所需 [[Prototype]] 的新对象,使用 Object.create()

MDN > JavaScript > Object.setPrototypeOf()

我想知道是否有任何情况下您可以修改对象的原型而不会导致级联优化效果影响程序的性能。好像应该有。例如,如果您仅在创建对象之后(以及在其被其他任何东西使用之前)修改原型。但我想这非常依赖引擎。

那么有人知道是否有有效的方法来修改对象的原型吗?

编辑:提出这个问题的动机是希望创建实际继承自Function 的对象。我知道如何做到这一点的唯一方法是修改函数的原型。在此处查看 Raynos 答案的最底部:javascript class inherit from Function class

【问题讨论】:

  • 你可以使用Object.assign(Object.create(obj), { obj2, obj3, obj4 }) 来创建一个带有 obj 原型的新对象。我相信它来自 Eric Elliot 的一本书。它获得了更好的内存占用。我希望我能给你一个更好的定义,但它与 Object.create() 实际上并不实例化一个新对象有关,所以它比从另一种方式获取原型要快。尝试谷歌搜索“Object.create memory performance”之类的内容。我想你可能会找到很多好材料。
  • 包括“效率”和“性能”在内的任何问题都应包括用于比较已尝试的各种代码模式的基准;得出基准的代码;以及代码在不同浏览器上的结果。否则,调查是基于纯粹的猜测,肯定有可能给出明确的答案。
  • 顺便说一句,那里有is a way to create objects inheriting from Function without setting the prototype,但是设置原型还是要舒服得多。是的,“如果你只在对象创建后立即修改原型”确实应该是这个规则的一个(或:唯一的)例外,但是我无法证明它。

标签: javascript inheritance prototype prototypal-inheritance prototype-chain


【解决方案1】:

提出这个问题的动机是希望创建实际继承自 Function 的对象。

看来您正在尝试执行以下操作:

  • 创建对象
  • 将这些对象的原型(或__proto__ 属性)设置为引用Fuction.prototype,以便它们从Function.prototype 继承属性,例如:
    • .apply
    • .call
    • .bind

您永远不需要更改任何对象的原型,只要您可以在创建对象时将其正确设置为所需的引用。


答案一:如何设置对象的原型

您可以在创建时使用Object.create() 设置任何对象的原型。请注意,将任何对象的原型分配给Function.prototype不会导致该对象成为可调用函数。但如果您仍想将原型分配给 Function.prototype 或其他对象,您可以执行以下操作:

var obj1 = Object.create(Function.prototype);

这将:

  • 创建一个新对象,obj1
  • 将其原型(或__proto__ 属性)设置为引用Function.prototype 或作为参数传入的任何对象
    • 即,它将通过 prototype chain 将失败的属性查找委托给 Function.prototype(这是 JavaScript 原型,__proto__ 指的是:委托失败的属性查找的地方)

要求您使用Object.setPrototypeOf() 来更改现有对象的原型,因为它在创建对象时分配原型。有关更多示例和信息,请参见 Object.create() 的 MDN 文档——这与 setPrototypeOf() 不带有相同的可怕警告。您可以使用Object.create() 设置任何新对象的原型。


答案二:函数已经是对象了

也就是说,如果你想要一个行为像函数的对象,你可以简单地创建一个函数。函数仍然是一个对象,但具有额外的特定于函数的属性和行为;您仍然可以通过为其分配属性来将其视为对象。如果您希望创建一个也像对象一样工作的函数,或者一个也可以做与函数相同的事情的对象,那么函数已经做到了。您可以执行以下操作:

var func = function() { return 'hello world'; }; // func is a function
func.property1 = 'foo'; // func is also an object
func.property2 = 'bar';

您的问题的最佳解决方案可能是利用函数实际上已经是具有附加功能能力的对象这一事实。

【讨论】:

  • 让不可调用的对象继承Function.prototype 方法是没有意义的。而Object.create 无法创建可调用对象。
  • 同意!也就是说,知道如何使用 Object.create() 来分配新对象的原型仍然很重要,所以我认为值得包括
猜你喜欢
  • 1970-01-01
  • 2014-07-12
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
相关资源
最近更新 更多