我已经阅读了很多关于对象原型属性的精彩文章和讨论(如this one),但这里有一个很大的问题。当我们观察“ prototype ”属性的行为时,我们意识到它实际上是另一个对象。我们可以看到它有一个像对象一样的 proto 和构造函数属性。
var myobj= function(){};
myobj.prototype.constructor== myobj --> true
所以这些是问题:
__proto__
是查找链中用于解析方法等的实际对象。 prototype 是用于构建 {{的对象1}} 使用 new “创建对象时。但我们可以看到,这不仅仅是原型的作用。我认为: Prototype就像对象的所有共享方法和属性的容器对象!然后,当使用 new 创建对象的实例时,其内部[ [Prototype]]指向原型,其中类的共享行为和属性暴露给实例!
这是真的吗? 最后:看来,当我们实例化一个类时,实例的构造函数被设置为该对象原型的构造函数。这个结论能否成立?
__proto__
答案 0 :(得分:5)
myobj
函数确实有.prototype
属性,原型对象作为其值。Object.prototype
。它有一个自己的.constructor
属性,其myobj
函数作为其值。 (It's really just a property).__proto__
是内部[[Prototype]]字段的非标准访问器。因此,它们通常被用作同义词。.constructor
属性。所有发生的事情是新实例继承自原型对象,而原型对象具有constructor
属性。请注意,示例中的myobj.prototype={};
对先前构造的实例没有影响。答案 1 :(得分:1)
我知道有一个公认的答案,但似乎对原型是什么,构造函数是什么以及它们如何相互作用存在一些混淆。
以此对象为例:
var foo = {
bar : 'hello',
sayBar : function(){
alert(this.bar);
}
};
您可以照原样使用它,就像您期望的那样。您可以重新分配foo.bar
并使用sayBar
方法,而不会出现任何问题:
foo.bar = 'Goodbye';
foo.sayBar(); //alerts(Goodbye);
现在说你需要拥有一堆所有需要bar
属性但具有不同值的对象。这时你可以创建一个构造函数来创建唯一的实例:
var fooClass = function(newbar){
this.bar = newbar;
};
可以像这样调用:
var myFoo = new fooClass('baz');
console.log(myFoo.bar); //logs 'baz'
这可以在幕后分解:
var fooClass = function(newbar){
//**IF 'new' is declared ** create an instance object, for now it has no declared prototype other than Object's base prototype
//That instance of the prototype is now scoped to 'this'
//it sets the 'constructor' of the instance behind the scenes
//this.constuctor = [our constructor function]
// now we can assign values to our instance and invoke it's methods
this.bar = newbar;
// our instance now has a key 'bar' that has the value of newbar
// so our instance now looks like this:
//
// {
// bar : [newbar]
// }
// return our instance object { bar : [newbar] }
};
这是原型对象发挥作用的地方。我们将foo
对象用作fooClass
原型:
var fooClass = function(newbar){
this.bar = newbar;
};
fooClass.prototype = foo;
现在,正如您所期望的那样,您可以使用foo
的方法:
var myFoo = new fooClass('baz');
myFoo.sayBar(); //alerts baz
现在这是构造函数正在做的事情:
var fooClass = function(newbar){
//**IF 'new' is declared ** create an instance object, which uses foo as it's prototype
//That instance of the prototype is now scoped to 'this'
//it sets the 'constructor' of the instance behind the scenes
//this.constuctor = [our constructor function]
// now we can assign values to our instance and invoke it's methods
this.bar = newbar;
// we have now overridden foo's default foo.bar with our instance bar
// so our instance now looks like this:
//
// {
// bar : [newbar], //overridden in constructor
//
// //with access to foo's methods through the prototype chain
// sayBar : function(){
// alert(this.bar);
// }
// }
// return our instance object
};
没有什么神奇的事情发生,所有构造函数都在做的是创建并返回一个对象实例,所有.prototype =
正在做的就是为该对象设置原型。
如果忘记'新'会怎样?
如果在使用构造函数时不使用new,则不会创建或返回新的对象实例。这就是为什么经常检查你的当前实例是否具有正确的构造函数:
var fooClass = function(newbar){
if(!(this instanceof fooClass)){ //if this constructor != fooClass
return new fooClass(newbar); //refire constructor with 'new'
}
//...
};