JavaScript面向對象(二)——成員屬性、靜態屬性、原型屬性與JS原型鏈

前  言html

上一篇博客(http://www.javashuo.com/article/p-trawluqe-bs.html )中,咱們介紹了JS中的面向對象,並詳細的解釋了this的指向問題。本篇博客,咱們繼續來學習JS的面向對象。來深刻理解一下JavaScript OOP中的成員屬性/方法、靜態屬性/方法、原型屬性/方法,而且一塊兒來探討一下JS中的原型與原型鏈。數組

 

一 成員屬性與成員方法函數

在構造函數中,經過this.屬性聲明。或者實例化出對象後,經過「對象.屬性」追加的。都屬於成員屬性、或成員方法;也叫實例屬性與實例方法學習

成員屬性/方法,是屬於實例化出的這個對象。經過"對象.屬性"調用this

代碼實例:spa

function Person(name){

this.name = name;//聲明成員屬性

this.say =function(){}//聲明成員方法

}

var zhangsan =new Person("張三");

zhangsan.age= 14;//追加成員屬性
alert(zhangsan.name);//調用成員屬性
zhangsan.say();//調用成員方法

 

二 靜態屬性與靜態方法prototype

經過"類名.屬性名","類名.方法名"聲明的變量,成爲靜態屬性、靜態方法;也叫類屬性、類方法3d

類屬性/類方法,是屬於類的(屬於構造函數的),這類屬性或方法必須經過"類名.屬性"調用,而不一樣經過對象名調用。code

代碼實例:htm

functionPerson(name){

}

Person.sex= "男";//聲明類屬性
alert(Person.age);//調用類屬性
var zhangsan = new Person("張三");

alert(zhangsan.sex);//沒法調用。類屬性只能用類名調用。

 

三 私有屬性與私有方法

在構造函數中,經過var聲明的屬性,成爲私有屬性。

私有屬性的做用域,僅在當前函數有效。對外不公開,即經過對象/類都沒法調用到。

代碼示例:

function Person(name){
    var sex = "男";

    alert(sex);//私有屬性只能在類內容使用。
}

alert(Person.sex);//沒法調用。私有屬性只能在類內容使用。

var zhangsan =new Person("張三");

alert(zhangsan.sex);//沒法調用。私有屬性只能在類內容使用。

 

四 原型屬性與原型方法

寫在了構造函數的prototype上。當使用構造函數實例化對象事,該屬性方法會進入新對象的__proto__上。

代碼示例:

functionPerson(){

}

Person.prototype.name4= "name4";//聲明原型屬性Person.prototype.say = function(){

}//聲明原型方法

var zhangsan =new Person();

alert(zhangsan.name);//可使用對象調用原型屬性
zhangsan.say();//可使用對象調用原型方法

 

經過上述代碼示例,咱們能夠發現:原型屬性和原型方法、成員屬性和成員方法,均可以使用對象名調用。那麼,成員屬性和原型屬性到底有什麼不一樣。咱們先來看這樣的一幅圖:


 

看出點門道了嗎?成員屬性是直接聲明在對象自身上!!而原型屬性是聲明在對象的__proto__上!!!在咱們使用「對象名.屬性名」訪問一個屬性時,會先訪問成員屬性,若是成員屬性中找不到,JS會沿着對象的原型鏈,繼續經過__proto__向上查找,也就找到了原型屬性。 這就是咱們可使用「對象名.屬性名」訪問成員屬性和原型屬性的緣由。

可是,說了這麼多,什麼是__proto__?什麼是prototype?什麼又是原型鏈?接下來,咱們就講解一下JS面向對象中最重要的一環——原型與原型鏈。

 

五 原型與原型鏈

1__proto__ 與 prototype

要講解原型與原型鏈,首先,咱們要了解兩個基本概念——__proto__和prototype。

①  prototype(函數的原型對象):函數纔有prototype,並且全部函數必有prototype。prototype是一個對象,指向了當前構造函數的引用地址呢。

②  __proto__(對象的原型):對象纔有__proto__,並且全部對象必有__proto__屬性(這裏的對象除了咱們理解的狹義對象,也包括了函數、數組等對象)。當用構造函數實例化(new)一個對象時,會將新對象的__proto__屬性,指上構造函數的prototype。

來看個案例:

functionPerson(){

}varzhangsan =newPerson();

console.log(zhangsan.__proto__== Person.prototype);//true//【解釋】上例中,咱們使用函數Person,new出了一個對象zhangsan。 那麼對象zhangsan的__proto__就等於函數Person的prototype。

2原型鏈

上面咱們介紹了對象的__proto__和函數的prototype。知道了對象的__proto__指向了函數的prototype。那麼,咱們也說了,函數的prototype自己也是個對象,是對象確定也有__proto__,那他的__proto__指向了誰? 順着這個問題,咱們延着一個對象__proto__向上查找,這條線路就是咱們所說的原型鏈。

因此,要研究原型鏈的走向,其實就是研究各類類型對象的__proto__到底指向誰。還記得上篇博客的「飛魚老師this五大準則」嗎? 此次,貼心的飛魚老師老師又爲你們準備了「飛魚老師原型鏈四大法則」,一塊兒來看看吧!

【飛魚老師原型鏈四大準則】

① 經過構造函數,new出的對象,新對象的__proto__指向構造函數的prototype

② 全部函數的__proto__指上Function()的prototype

③ 非構造函數new出的對象( {}  new Object()對象的prototype)的__proto__指向Object的prototype

④Object的prototype的__proto__指向null

字不如表,表不如圖。咱們一塊兒以一段代碼爲例,探討一下原型鏈。

代碼:

functionPerson(){

}

varzhangsan =newPerson();

 

 

就是這樣一個簡單的類new出對象,咱們來探討一下原型鏈吧~上圖!!!

原型鏈圖(飛魚老師親情手繪,親,點個讚唄!):


 

六 成員屬性與原型方法

說了這麼多,咱們應該可以理解原型與原型鏈,也深入的理解了原型屬性、原型方法。那麼問題來了,既然成員屬性/方法和原型屬性/方法,都能經過對象名訪問。咱們到底用那種比較好呢?

習慣上,咱們會將屬性寫爲成員屬性,而方法寫爲原型方法

緣由以下:

① 實例化出對象後,全部屬性直接在對象上,全部方法都在__proto__上,很是直觀清晰。

② 方法寫到prototype上,要更加節省內存;

③ 使用for in循環時,會將對象以及對象原型鏈上的全部屬性和方法打印出來,而方法每每是不須要展現的。 將方法寫到__proto__上,可使用hasOwnProperty將原型上的方法過濾掉、不顯示。


④ 官方都這麼寫。

 

七 prototype擴展內置函數

那原型還有什麼做用呢?還有一個最經常使用的,就是咱們使用prototype擴展內置函數的方法。能夠直接使用內置函數的對象,調用咱們擴展的方法;

好比,爲Array類添加一個find(val)方法,當一個Array對象調用該方法的時候,若是能找到val值,則返回其下標,不然返回-1。

Array.prototype.find =function(val){
//在Array類的原型上添加擴展方法

}

var arr =new Array(1,2,3,4,5);

alert(arr.find(1));//直接使用Array類的對象,也就是數組,就能夠調用這個方法

 

好了,今天的課程就先到這裏吧?咱們學習了JS中的成員屬性、靜態屬性、原型屬性、私有屬性等各類學習。 也學習了JS面向對象中很是重要的一個環節——原型與原型鏈。你都學會了嗎? 若是有問題歡迎你們評論留言哦~~咱們下次課再見吧!

相關文章
相關標籤/搜索