Javascript 什么';这两种原型继承实现之间的区别是什么?

Javascript 什么';这两种原型继承实现之间的区别是什么?,javascript,inheritance,prototype,prototypal-inheritance,Javascript,Inheritance,Prototype,Prototypal Inheritance,这两个原型继承的实现之间有什么区别,考虑到我们使用的是两个不同的“原型”(仅在函数上的原型属性和内部原型),这些实现在原型链查找方面有什么区别?另外,第一个实现(使用prototype属性)是否依赖于我们对新操作符的使用 分配给函数的原型属性,并使用新的运算符: function foo() {} foo.prototype.output = function(){ console.log('inherits from Function.prototype property'); };

这两个原型继承的实现之间有什么区别,考虑到我们使用的是两个不同的“原型”(仅在函数上的原型属性和内部原型),这些实现在原型链查找方面有什么区别?另外,第一个实现(使用prototype属性)是否依赖于我们对
操作符的使用

分配给函数的
原型
属性,并使用
新的
运算符:

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
),并且它有一个主要缺陷:在没有
new
的情况下调用一个添加属性的构造函数(
this.name=nameParam
…),会将构造应用于全局对象。构造函数的行为很奇怪(创建新对象,委托给
SomeConstructor.prototype
,然后将构造函数应用于新对象,如果构造函数返回某物,则用某物替换该对象)。另外,在您的示例中,
foo
本身不可用,您必须创建一个新对象才能访问其功能

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

,以及关于原型代表团

现在,查找是如何进行的:

  • 使用构造函数,可以在
    constructor.prototype
    上进行查找(不是构造函数的实际内部原型,而是它的
    prototype
    属性。如果您发现它令人困惑,恭喜您,您是人类)。其他属性在构造函数中设置
    foo
    本身不用于查找,
    foo.prototype
    (与指向函数的
    foo
  • 使用
    Object.create
    可以对对象本身进行查找(
    foo
    )。对象上没有
    prototype
    non-prototype属性
还有一个更进一步的解释


关于此问题中的新
的更多信息:

第一个示例-foo是一个函数

第二个示例-foo是一个对象

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


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

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

现在,您必须知道,如果将
null
作为参数传递,则上述代码不会产生相同的结果。
用于创建新对象(阅读更多内容)的ECMAScript算法指出,如果函数的原型设置为
null
(或任何非对象),当您尝试使用
new f()
语法时,新创建的对象将继承自
对象。原型

如果您使用
Object.create(null)
,新创建的对象将其
[[Prototype]]
内部成员设置为
null
,这意味着原型链将停止在那里(您的对象不会像普通对象那样从
Object.Prototype
获取
hasOwnProperty
和其他内容)


一个区别是,
Object.create
较新,在IE8中不受支持,belowI在您的示例中看不到原型继承。@后面的请详细说明一下好吗?我认为@hindmost的意思是它不是继承(从上到下),而是委托。对象依赖于其他对象的功能,而不是依赖于它们的“祖先”,因为它们没有任何功能。凯尔获取了凯尔·辛普森关于该主题的图表。我建议自己阅读整个链接章节。@Kyll关于“查找”有什么不同?这些实现使用了两个不同的
prototype
对象,不是吗?我想说的是,在这两个实现中委托是如何发生的?它们在跟踪原型查找的方式上有什么不同?你能发布一个简单的图表吗?凯尔·辛普森做了一个惊人的图表,如果可以的话让我去拿。
function create (proto) {
  function f () {}
  f.prototype = proto;
  return new f();
}
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