Js原型鏈constructor prototype __proto__屬性實(shí)例詳解
導(dǎo)讀
__proto__(實(shí)際原型)和prototype(原型屬性)不一樣?。。?/p>
constructor屬性(原型對(duì)象中包含這個(gè)屬性,實(shí)例當(dāng)中也同樣會(huì)繼承這個(gè)屬性)
prototype屬性(constructor.prototype原型對(duì)象)
__proto__屬性(實(shí)例指向原型對(duì)象的指針)
首先弄清楚幾個(gè)概念:
什么是對(duì)象?
若干屬性的集合
什么是原型?
原型是一個(gè)對(duì)象,其他對(duì)象可以通過它實(shí)現(xiàn)繼承。
哪些對(duì)象有原型?
所有的對(duì)象在默認(rèn)情況下都有一個(gè)原型,因?yàn)樵捅旧硪彩菍?duì)象,所以每個(gè)原型自身又有一個(gè)原型(只有一種例外,默認(rèn)的對(duì)象原型在原型鏈的頂端)
任何一個(gè)對(duì)象都可以成為原型
接下來就是最核心的內(nèi)容:
constructor 屬性
constructor屬性始終指向創(chuàng)建當(dāng)前對(duì)象的構(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(){}以上部分即解釋了任何一個(gè)對(duì)象都有constructor屬性,指向創(chuàng)建這個(gè)對(duì)象的構(gòu)造函數(shù)
prototype屬性
注意:prototype是每個(gè)函數(shù)對(duì)象都具有的屬性,被稱為原型對(duì)象,而__proto__屬性才是每個(gè)對(duì)象才有的屬性。一旦原型對(duì)象被賦予屬性和方法,那么由相應(yīng)的構(gòu)造函數(shù)創(chuàng)建的實(shí)例會(huì)繼承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屬性
每個(gè)函數(shù)都有prototype屬性,而這個(gè)prototype的constructor屬性會(huì)指向這個(gè)函數(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(){}如果我們重寫(重新定義)這個(gè)Person.prototype屬性,那么constructor屬性的指向就會(huì)發(fā)生改變了。
Person.prototype={
sayName:function(){
console.log(this.name);
}
}
console.log(person.constructor==Person); //輸出 false (這里為什么會(huì)輸出false后面會(huì)講)
console.log(Person.constructor==Person); //輸出 false
console.log(Person.prototype.constructor);// 輸出 function Object(){}
//這里為什么會(huì)輸出function Object(){}
//還記得之前說過constructor屬性始終指向創(chuàng)建這個(gè)對(duì)象的構(gòu)造函數(shù)嗎?
Person.prototype={
sayName:function(){
console.log(this.name);
}
}
//這里實(shí)際上是對(duì)原型對(duì)象的重寫:
Person.prototype=new Object(){
sayName:function(){
console.log(this.name);
}
}
//看到了吧?,F(xiàn)在Person.prototype.constructor屬性實(shí)際上是指向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
//大家可能會(huì)對(duì)這個(gè)地方產(chǎn)生疑惑?為何會(huì)第二個(gè)會(huì)輸出false,personTwo不也是由Person創(chuàng)建的嗎?這個(gè)地方應(yīng)該要輸出true???
//這里就涉及到了js里面的原型繼承
//這個(gè)地方是因?yàn)閜erson實(shí)例繼承了Person.prototype原型對(duì)象的所有的方法和屬性,包括constructor屬性。當(dāng)Person.prototype的constructor發(fā)生變化的時(shí)候,相應(yīng)的person實(shí)例上的constructor屬性也會(huì)發(fā)生變化。所以第二個(gè)會(huì)輸出false;
//當(dāng)然第一個(gè)是輸出true,因?yàn)楦淖儤?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ù)的原型對(duì)象Person.prototype賦給sayName方法,由構(gòu)造函數(shù)Person創(chuàng)建的實(shí)例person會(huì)繼承原型對(duì)象上的sayName方法。
為什么會(huì)繼承原型對(duì)象的方法?
因?yàn)镋CMAscript的發(fā)明者為了簡化這門語言,同時(shí)又保持繼承性,采用了鏈?zhǔn)嚼^承的方法。
由constructor創(chuàng)建的每個(gè)instance都有個(gè)__proto__屬性,它指向constructor.prototype。那么constrcutor.prototype上定義的屬性和方法都會(huì)被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__屬性實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于Js 原型鏈屬性的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序中頂部導(dǎo)航欄的實(shí)現(xiàn)代碼
這篇文章主要介紹了微信小程序中頂部導(dǎo)航欄的實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
微信小程序 詳解下拉加載與上拉刷新實(shí)現(xiàn)方法
這篇文章主要介紹了微信小程序 詳解下拉加載與上拉刷新實(shí)現(xiàn)方法的相關(guān)資料,這里介紹了兩種實(shí)現(xiàn)方法,需要的朋友可以參考下2017-01-01
微信小程序 scroll-view組件實(shí)現(xiàn)列表頁實(shí)例代碼
這篇文章主要介紹了微信小程序 scroll-view組件實(shí)現(xiàn)列表頁實(shí)例代碼的相關(guān)資料,scroll-view組件介紹scroll-view是微信小程序提供的可滾動(dòng)視圖組件,其主要作用是可以用來做手機(jī)端經(jīng)常會(huì)看到的上拉加載 ,需要的朋友可以參考下2016-12-12

