这两种原型继承的实现有什么区别?
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
,这意味着原型链将停在那里(你的对象没有得到hasOwnProperty
和 Object.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
这两种原型继承的实现有什么区别,考虑到我们正在使用 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
,这意味着原型链将停在那里(你的对象没有得到hasOwnProperty
和 Object.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