这两种原型继承的实现有什么区别?

What's the difference between these 2 implementations of prototypal inheritance?

这两种原型继承的实现有什么区别,考虑到我们正在使用 2 种不同的 "prototypes"(仅在函数上的原型 属性 和内部原型),这些实现在原型链查找方面有何不同?另外,第一个实现(使用原型 属性)是否依赖于我们对 new 运算符的使用?

分配给函数的 prototype 属性 并使用 new 运算符:

function foo() {}

foo.prototype.output = function(){
   console.log('inherits from Function.prototype property');
};

bar = new foo();
bar.output();

在对象字面量中存储函数并使用Object.create()方法:

var foo = {
  output: function(){
    console.log('inherits from the internal prototype');
  }
};

var bar = Object.create(foo);
bar.output();

主要区别在于它的使用方式以及相关的危险。

第一个强制您在要创建新对象时使用 new。语法相当难看 (SomeConstructor.prototype.method),并且它有一个主要缺陷:调用一个添加属性 (this.name = nameParam...) 的构造函数而没有 new 会将构造应用于全局对象.构造函数的行为很奇怪(创建委托给 SomeConstructor.prototype 的新对象,然后将构造函数应用于新对象,然后如果构造函数 returns something 将对象替换为 something)。另外,在您的示例中,foo 本身不可用,您必须创建一个新对象才能访问其功能。

第二个 Object.create 不会强迫您使用任何语法怪癖。你没有全球污染风险。对象 foo 具有无需创建新对象即可使用的功能,而 bar 将简单地借用这些功能。这种模式还可以更容易地实现工厂(无需 new 到处替换)和对象池(如果需要的话)。

Eric Eliott talks about it very well, and Kyle Simpson wrote a whole book关于原型委托!

现在,查找是这样进行的:

  • 对于构造函数,查找是在 Constructor.prototype 上完成的(不是构造函数的 actual 内部原型,而是它的 prototype属性. 如果你发现它令人困惑,恭喜你,你是人)。其他属性在构造函数中设置。 foo 本身不用于查找,foo.prototype(同样,与指向函数的 foo.__proto__ 不同)是用于它的。
  • 使用 Object.create 查找是在对象本身 (foo) 上完成的。对象上没有 prototype 非原型 属性。

very funny diagrams on this page of Kyle Simpson's book 进一步解释了事情。

更多关于 new 的问题:Is JavaScript's "new" keyword considered harmful?

第一个例子 - foo,是一个函数。

第二个例子 - foo 是一个对象。

在第二个示例中,bar 成为一个没有构造函数的新实例。 请参阅 - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/create,以添加构造函数。

作为旁注,构造函数应以大写字母开头是常见的最佳实践。

好的,首先,如果你不知道,Object.create 是基于 Douglas Crockford 提出的以下模式(阅读更多 here):

function create (proto) {
  function f () {}
  f.prototype = proto;
  return new f();
}

现在,您必须知道如果将 null 作为参数传递,上述代码不会产生相同的结果。
用于创建新对象的 ECMAScript 算法(阅读更多 here)指出,如果函数的原型设置为 null(或任何非对象),当您尝试使用 new f()语法,新创建的对象会继承自Object.prototype.
如果你使用Object.create(null),新创建的对象会将其[[Prototype]]内部成员设置为null,这意味着原型链将停在那里(你的对象没有得到hasOwnPropertyObject.prototype 中的其他东西,就像普通对象一样)。

var o1 = create(null);
var o2 = Object.create(null);
Object.getPrototypeOf(o1) === Object.prototype // true
Object.getPrototypeOf(o2) === Object.prototype // false
Object.getPrototypeOf(o2) === null // true