Extends Object.setPrototypeOf()与Object.create的区别

6

我知道两种继承函数构造器的方法。

选项1 Object.create

function x(x, y) {
  this.x = x;
  this.y = y;
}

x.prototype.XDD = function() {};


function y(c, r) {
  x.call(this, 1, 2);
  this.r = r;
  this.c = c;
}

y.prototype = Object.create(x.prototype);
y.prototype.YDD = function() {};
y.prototype.XDD = function() {};
y.prototype.constructor  = y;

var rect = new y(1, 2);

选项2 Object.setPrototypeOf()

function x(x, y) {
  this.x = x;
  this.y = y;
}

x.prototype.XDD = function() {};

function y(c, r) {
  x.call(this, 1, 2);
  this.r = r;
  this.c = c;
}

y.prototype.YDD = function() {};
y.prototype.XDD = function() {};
Object.setPrototypeOf(y.prototype, x.prototype);

var rect = new y(1, 2);

它们之间有什么区别?还有其他比这些更好的解决方案吗?

4
回答最后一个问题,是的,有:class Foo extends Bar - georg
高手们在使用 JavaScript 时有所偏好,一些人更喜欢使用 class 关键字,因为它是基于 class 和 object 的,而 Object.create 则是基于 原型继承 的,只适用于某些情况。 - Satyam Pathak
尽管存在性能问题,但使用Object.setPrototypeOf()也意味着您可能希望在事件之后更改原型。我想不出一个真实的例子来解释为什么需要这样做,但是就是这样。 - Manngo
1个回答

3
根据MDN文档
更改对象的[[Prototype]]是一个非常缓慢的操作,因为现代JavaScript引擎如何优化属性访问的本质,目前在每个浏览器和JavaScript引擎中都是如此。此外,更改继承的影响是微妙而广泛的,并且不仅限于Object.setPrototypeOf(...)语句所花费的时间,还可能延伸到任何可以访问已更改[[Prototype]]的任何对象的代码。
由于这个特性是语言的一部分,因此引擎开发人员仍然需要实现该特性以提高性能(理想情况下)。在引擎开发人员解决此问题之前,如果您关心性能,应避免设置对象的[[Prototype]]。相反,使用Object.create()创建具有所需[[Prototype]]的新对象。

性能比较(2019年2月14日): https://gist.github.com/calebmer/c74e2a7941044e5f28b8#gistcomment-2836415

简而言之,当在极其大的规模下使用时,使用Object.create 使用Object.setPrototypeOf 快得多。

在JS中,还有许多其他设置对象原型的方法(例如不建议使用Object.prototype.__proto__),但现在(2019年10月)最推荐的方式似乎是使用ES6 classsupported 大多数现代浏览器都支持。尽管有一些基准测试(比如:this),表明ES6类和super()比它们的ES5对应物要慢,但这可以使你的代码更加干净,特别适合来自其他面向对象语言的人。


该基准测试与 OPs 代码做的事情非常不同。 - Bergi
并没有太大的不同 - 它基本上展示了Object.createObject.setPrototypeOf之间的区别。 - Beniamin H
1
但是在 OP 的代码中,使用 Object.create 调用和 Object.setPrototype 调用的性能差异并不重要。只有一个调用它们的地方,无论这需要多花费 3 纳秒还是不需要,都不会有影响。只有当 var rect = new y(1, 2);rect.YDD() 存在差异时,他才会关心。 - Bergi
1
实际上,这个问题不是关于创建对象或调用方法的,而是关于两种继承方式:Object.createObject.setPrototypeOf。我同意你的观点,在大多数情况下,你不会继承10^8次,但问题明确是关于继承的。 - Beniamin H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接