我一直在阅读Is JavaScript's "new" keyword considered harmful?和this Adobe Article on using prototypal inheritance rather than 'new'。 Adobe文章有一个“新”示例:
function Foo() {
this.name = "foo";
}
Foo.prototype.sayHello = function() {
alert("hello from " + this.name);
};
......它取代了:
var foo = {
name: "foo",
sayHello: function() {
alert("hello from " + this.name);
}
};
此处'sayHello'方法未附加到对象的prototype
。这是不是意味着'sayHello'在内存中不必要地重复(我知道V8避免了这种情况,但在旧的JS引擎中),因为它被复制到从foo
继承的所有对象?
不应该是:
var foo = {
name: "foo",
prototype: {
sayHello: function() {
alert("hello from " + this.name);
}
}
};
或者类似的?
答案 0 :(得分:2)
该方法未附加到原型,因为此对象成为使用Object.create
附加到新创建的对象的原型。而且你不需要原型的原型。
请记住,Object.create
不会深层克隆对象。相反,它等同于
Object.create = function(proto) {
function F() {}
F.prototype = proto;
return new F();
}
(实际实施更复杂,但这个简短的版本说明了这个想法)
所有新创建的对象都“继承”foo
中的方法,该方法充当原型,此处没有重复。
答案 1 :(得分:2)
不,如果您使用它作为原型创建另一个对象,它将不会重复。使用Object.create
的几乎等效的代码实际上略有不同,你没有使用原型,你只是创建一个对象。 To use prototypal inheritance, do the following。请注意,使用new
仍会设置原型链,因此您链接到的文章的标题不是很准确,并且您仍然在单个对象上共享属性。
var foo = {
name: "foo",
sayHello: function() {
alert("hello from " + this.name);
}
};
var extended = Object.create(foo);
var extended2 = Object.create(foo);
extended.name = "first";
extended2.name = "second";
extended.sayHello(); // hello from first
extended2.sayHello(); // hello from second
// Methods are shared, outputs true
console.log(extended.sayHello === extended2.sayHello)
// Now if you delete the property again, it will go up the chain
delete extended.name;
extended.sayHello(); // hello from foo
您也可以这样做
var extended = Object.create(Foo.prototype);
如果您创建构造函数来获取新实例而不是Object.create
或new Foo
function createFoo() {
return {
name: "foo",
sayHello: function() {
alert("hello from " + this.name);
}
}
}
var a = createFoo();
var b = createFoo();
// The function objects are not shared
alert('Are functions the same? ' + a.sayHello === b.createFoo);
如果使用闭包方法创建对象,也不会共享它们。克罗克福德建议创建真正的私人成员。我不使用它,因为它不使用原型链,并且继承是很难实现的,而不仅仅是复制属性。
Function Foo() {
var name = 'foo';
this.sayHello = function () {
alert(name);
};
this.setName = function (newName) {
name = newName;
};
}
var a = new Foo();
var b = new Foo();
console.log(a.sayHello === b.sayHello); // outputs false
答案 2 :(得分:0)
在这里回答我自己的问题,为了我自己的笔记,并帮助向他人解释:
Q值。使用Object.create(),样本是否应该将方法附加到
prototype
属性?
:一种。不,因为Object.create(parentObject)本身将parentObject设置为动态创建的构造函数的prototype
。
另外:prototype
始终是构造函数的属性 - 而不是常规对象。例如:
var someArray = [];
someArray.__proto__ === Array.prototype
Object.create()动态创建构造函数,将它们的原型设置为第一个参数中的对象。