Js原型鏈constructor prototype __proto__屬性實例詳解
導讀
__proto__(實際原型)和prototype(原型屬性)不一樣?。?!
constructor屬性(原型對象中包含這個屬性,實例當中也同樣會繼承這個屬性)
prototype屬性(constructor.prototype原型對象)
__proto__屬性(實例指向原型對象的指針)
首先弄清楚幾個概念:
什么是對象?
若干屬性的集合
什么是原型?
原型是一個對象,其他對象可以通過它實現(xiàn)繼承。
哪些對象有原型?
所有的對象在默認情況下都有一個原型,因為原型本身也是對象,所以每個原型自身又有一個原型(只有一種例外,默認的對象原型在原型鏈的頂端)
任何一個對象都可以成為原型
接下來就是最核心的內(nèi)容:
constructor 屬性
constructor屬性始終指向創(chuàng)建當前對象的構(gòu)造函數(shù)。
var arr=[1,2,3];
console.log(arr.constructor); //輸出 function Array(){} var a={}; console.log(arr.constructor);//輸出 function Object(){} var bool=false; console.log(bool.constructor);//輸出 function Boolean(){} var name="hello"; console.log(name.constructor);//輸出 function String(){} var sayName=function(){} console.log(sayName.constrctor)// 輸出 function Function(){} //接下來通過構(gòu)造函數(shù)創(chuàng)建instance function A(){} var a=new A(); console.log(a.constructor); //輸出 function A(){}
以上部分即解釋了任何一個對象都有constructor屬性,指向創(chuàng)建這個對象的構(gòu)造函數(shù)
prototype屬性
注意:prototype是每個函數(shù)對象都具有的屬性,被稱為原型對象,而__proto__屬性才是每個對象才有的屬性。一旦原型對象被賦予屬性和方法,那么由相應的構(gòu)造函數(shù)創(chuàng)建的實例會繼承prototype上的屬性和方法。
var arr=[1,2,3]; console.log(arr.constructor); //輸出 function Array(){} var a={}; console.log(arr.constructor);//輸出 function Object(){} var bool=false; console.log(bool.constructor);//輸出 function Boolean(){} var name="hello"; console.log(name.constructor);//輸出 function String(){} var sayName=function(){} console.log(sayName.constrctor)// 輸出 function Function(){} //接下來通過構(gòu)造函數(shù)創(chuàng)建instance function A(){} var a=new A(); console.log(a.constructor); //輸出 function A(){}
constructor屬性和prototype屬性
每個函數(shù)都有prototype屬性,而這個prototype的constructor屬性會指向這個函數(shù)。
function Person(name){ this.name=name; } Person.prototype.sayName=function(){ console.log(this.name); } var person=new Person("xl"); console.log(person.constructor); //輸出 function Person(){} console.log(Person.prototype.constructor);//輸出 function Person(){} console.log(Person.constructor); //輸出 function Function(){}
如果我們重寫(重新定義)這個Person.prototype屬性,那么constructor屬性的指向就會發(fā)生改變了。
Person.prototype={ sayName:function(){ console.log(this.name); } } console.log(person.constructor==Person); //輸出 false (這里為什么會輸出false后面會講) console.log(Person.constructor==Person); //輸出 false console.log(Person.prototype.constructor);// 輸出 function Object(){} //這里為什么會輸出function Object(){} //還記得之前說過constructor屬性始終指向創(chuàng)建這個對象的構(gòu)造函數(shù)嗎? Person.prototype={ sayName:function(){ console.log(this.name); } } //這里實際上是對原型對象的重寫: Person.prototype=new Object(){ sayName:function(){ console.log(this.name); } } //看到了吧?,F(xiàn)在Person.prototype.constructor屬性實際上是指向Object的。 //那么我如何能將constructor屬性再次指向Person呢? Person.prototype.constructor=Person;
接下來解釋為什么,看下面的例子
function Person(name){ this.name = name; } var personOne=new Person("xl"); Person.prototype = { sayName: function(){ console.log(this.name); } }; var personTwo = new Person('XL'); console.log(personOne.constructor == Person); //輸出true console.log(personTwo.constructor == Person); //輸出false //大家可能會對這個地方產(chǎn)生疑惑?為何會第二個會輸出false,personTwo不也是由Person創(chuàng)建的嗎?這個地方應該要輸出true?。? //這里就涉及到了js里面的原型繼承 //這個地方是因為person實例繼承了Person.prototype原型對象的所有的方法和屬性,包括constructor屬性。當Person.prototype的constructor發(fā)生變化的時候,相應的person實例上的constructor屬性也會發(fā)生變化。所以第二個會輸出false; //當然第一個是輸出true,因為改變構(gòu)造函數(shù)的prototype屬性是在personOne被創(chuàng)建出來之后。
__proto__和prototype屬性
同樣拿上面的代碼來解釋:
function Person(name){ this.name=name; } Person.prototype.sayName=function(){ console.log(this.name); } var person=new Person("xl"); person.sayName(); //輸出 "xl" //constructor : Person //instance : person //prototype : Person.prototype //constructor : Person //instance : person //prototype : Person.prototype
首先給構(gòu)造函數(shù)的原型對象Person.prototype賦給sayName方法,由構(gòu)造函數(shù)Person創(chuàng)建的實例person會繼承原型對象上的sayName方法。
為什么會繼承原型對象的方法?
因為ECMAscript的發(fā)明者為了簡化這門語言,同時又保持繼承性,采用了鏈式繼承的方法。
由constructor創(chuàng)建的每個instance都有個__proto__屬性,它指向constructor.prototype。那么constrcutor.prototype上定義的屬性和方法都會被instance所繼承。
function Person(name){ this.name=name; } Person.prototype.sayName=function(){ console.log(this.name); } var personOne=new Person("a"); var personTwo=new Person("b"); personOne.sayName(); // 輸出 "a" personTwo.sayName(); //輸出 "b" console.log(personOne.__proto__==Person.prototype); // true console.log(personTwo.__proto__==Person.prototype); // true console.log(personOne.constructor==Person); //true console.log(personTwo.constructor==Person); //true console.log(Person.prototype.constructor==Person); //true console.log(Person.constructor); //function Function(){} console.log(Person.__proto__.__proto__); // Object{}
以上就是Js原型鏈constructor prototype __proto__屬性實例詳解的詳細內(nèi)容,更多關于Js 原型鏈屬性的資料請關注腳本之家其它相關文章!
相關文章
微信小程序 scroll-view組件實現(xiàn)列表頁實例代碼
這篇文章主要介紹了微信小程序 scroll-view組件實現(xiàn)列表頁實例代碼的相關資料,scroll-view組件介紹scroll-view是微信小程序提供的可滾動視圖組件,其主要作用是可以用來做手機端經(jīng)常會看到的上拉加載 ,需要的朋友可以參考下2016-12-12