總結:
1、對象有屬性_proto_,指向prototype。a. 對象的_proto_指向其構造方法的原型對象。b. 原型對象的_proto_指向上一級原型對象。c. Object.prototype._proto_=null
foo——>Foo.prototype——>Object.prototype(上一級原型對象)——>null
Foo()——>Function.prototype(構造方法可看成Function的實例)——>Object.prototype(上一級原型對象)——>null
2、方法除了有_proto_,還有屬性prototype,指向該方法的原型對象。
Foo()——>Foo.prototype
3、每個對象都有constructor指針,a. 指向創建該對象實例的構造函數。b. 原型對象指向對應的構造函數
Foo.prototype——>Foo()——>Function(Foo是Function的實例)
foo——>Foo()——>Function
然後祭出一張經典圖
實例:
function Girl(name) { this.name=name; this.getName=function () { console.log(this.name); } } Girl.prototype.getName=function () { console.log("原型名字"); } Girl.prototype.age=function () { console.log('原型年齡') } function Boy(name) { Girl.call(this,name); } var Peter=new Boy('Peter'); var Mary=new Girl('Mary'); Peter.getName(); //'Peter'————通過call繼承了Girl構造函數中的性質 //Peter.age(); //not a function————無法繼承Girl原型中的性質。與Girl原型毫無關係。 Mary.getName(); //"Mary"————會先查找實例中是否有該方法,因此原型中的同名方法不被執行。 Mary.constructor.prototype.getName(); //"原型名字"————執行原型同名方法的方式:Mary.constructor指向Girl。 Girl.prototype={ //這種對象賦值的方法等同於重寫原型。若放在實例化之後,會切斷實例與原型的聯繫。 constructor:Girl, age:function () { console.log('新原型年齡'); } }; Mary.age(); //"原型年齡"————實例仍指向舊原型,與新原型無關 Mary.constructor.prototype.age(); //"新原型年齡"————構造方法的prototype指向新原型 Mary.constructor.prototype.getName(); //not a function————新原型中無getName()方法。 Girl('jj'); //直接這樣執行,this指向Windows,將name掛到windows上 getName(); //"jj"————讀取了Windows上的name.