JS原型鏈和訪問對象原型的方法

大家好,我是IT修真院深圳分院第01期學員,一枚正直純潔善良的web程序員。

今天給大家分享一下,修真院官網JS(職業)任務4,深度思考中的知識點——JS原型鏈和訪問對象原型的方法

1.介紹

JavaScript 中,萬物皆對象。JavaScript根據"原型鏈"(prototype chain)模式,來實現繼承。

2.涉及

2.1對象

JavaScript中,對象是有區別的,分為普通對象和函數對象,Object ,Function 是JS自帶的函數對象,function定義方式本質上還是new Function方式。

function? f1(){};

var?f2?=?function(){};

var?f3?=?new?Function('str','console.log(str)');

var o3 = new f1();

var?o1?=?{};

var?o2?=new?Object();

console.log(typeof? Object); ?//function

console.log(typeof? Function); ?//function

console.log(typeof?o1);???//object

console.log(typeof?o2);???//object

console.log(typeof?o3);???//object

console.log(typeof? f1);???//function

console.log(typeof? f2);???//function

console.log(typeof ?f3);???//function

2.2對象繼承

Brendan Eich參考C++和Java,做了簡化設計,將new命令引入JavaScript中,new后面跟對象的構造函數,用來創建對象。這樣做有個缺點:無法共享方法和屬性。

比如,在DOG對象的構造函數中,設置一個實例對象的共有屬性species。

function DOG(name){

this.name = name;

this.species = '犬科';

}

然后,生成兩個實例對象:

var dogA = new DOG('大毛');

var dogB = new DOG('二毛');

這兩個對象的species屬性是獨立的,修改其中一個,不會影響到另一個。

dogA.species = '貓科';

alert(dogB.species); // 顯示"犬科",不受dogA的影響

每一個實例對象,都有自己的屬性和方法的副本。這不僅無法做到數據共享,也是極大的資源浪費。

Brendan Eich決定為構造函數設置一個prototype屬性。這個屬性包含一個對象,所有實例對象需要共享的屬性和方法,都放在這個對象里面;那些不需要共享的屬性和方法,就放在構造函數里面。實例對象一旦創建,將自動引用prototype對象的屬性和方法。也就是說,實例對象的屬性和方法,分成兩種,一種是本地的,另一種是引用的。

function DOG(name){

this.name = name;

}

DOG.prototype = { species : '犬科' };

var dogA = new DOG('大毛');

var dogB = new DOG('二毛');

alert(dogA.species); // 犬科

alert(dogB.species); // 犬科

species屬性放在prototype對象里,是兩個實例對象共享的。只要修改了prototype對象,就會同時影響到兩個實例對象。

DOG.prototype.species = '貓科';

alert(dogA.species); // 貓科

alert(dogB.species); // 貓科

由于所有的實例對象共享同一個prototype對象,那么從外界看起來,prototype對象就好像是實例對象的原型,而實例對象則好像"繼承"了prototype對象一樣。

2.3原型prototype

在JavaScript 中,每當定義一個對象(函數)時候,對象中都會包含一些預定義的屬性。其中函數對象的一個屬性就是原型對象 prototype。普通對象沒有prototype,但有__proto__屬性。

示例:

function? f1(){};

console.log(f1. prototype) //f1 {}

console.log(typeof ?f1. prototype) //object

console.log(typeof ?Function. prototype) // function

console.log(typeof ?Object. prototype) // object

console.log(typeof ?Function. prototype. prototype) //undefined

2.4 原型鏈

JS在創建對象(不論是普通對象還是函數對象)的時候,都有一個叫做__proto__的內置屬性,用于指向創建它的函數對象的原型對象prototype。

var person = function(name){

this.name = name

};

person.prototype.getName = function(){

return this.name;

}

var zjh = new person(‘zhangjiahao’);

zjh.getName(); //zhangjiahao

以上面的例子為例:

console.log(zjh.__proto__ === person.prototype) //true

同樣,person.prototype對象也有__proto__屬性,它指向創建它的函數對象(Object)的prototype

console.log(person.prototype.__proto__ === Object.prototype) //true

繼續,Object.prototype對象也有__proto__屬性,但它比較特殊,為null

console.log(Object.prototype.__proto__) //null

我們把這個有__proto__串起來的直到Object.prototype.__proto__為null的鏈叫做原型鏈。

2.5 constructor屬性

prototype對象有一個constructor屬性,默認指向prototype對象所在的構造函數。

由于constructor屬性定義在prototype對象上面,意味著可以被所有實例對象繼承。

constructor屬性的作用,是分辨原型對象到底屬于哪個構造函數。

2.6 總結

1.原型和原型鏈是JS實現繼承的一種模型。

2.原型鏈的形成是真正是靠__proto__ 而非prototype。

3.常見問題

訪問對象原型的方法有哪些?

4.解決方法

獲取實例對象obj的原型對象,有三種方法:

1. obj.__proto__

2. obj.constructor.prototype

3. Object.getPrototypeOf(obj)

上面三種方法之中,前兩種都不是很可靠。最新的ES6標準規定,__proto__屬性只有瀏覽器才需要部署,其他環境可以不部署。而obj.constructor.prototype在手動改變原型對象時,可能會失效。

5.編碼實戰

6.擴展思考

1.Object.__proto__ === Function.prototype // true

2.Function.__proto__ === Function.prototype // true

3.Function.prototype.__proto__ === Object.prototype //true

1.Object是函數對象,是通過new Function()創建,所以Object.__proto__指向Function.prototype。

2.Function 也是對象函數,也是通過new Function()創建,所以Function.__proto__指向Function.prototype。

3.Function.prototype是個函數對象,理論上其__proto__應該指向 Function.prototype,就是它自己,自己指向自己,沒有意義。函數對象也是對象,給它設定根指向Object.prototype,Object.prototype.__proto__ === null,保證原型鏈能夠正常結束。

7.參考文獻

參考一:阮一峰:Javascript繼承機制的設計思想

參考二:zhangjiahao8961:JavaScript原型及原型鏈詳解

8.更多討論

JavaScript 對象的繼承機制

鳴謝

感謝大家觀看

PPT鏈接

視頻鏈接


JS原型對象和原型鏈簡介_騰訊視頻

------------------------------------------------------------------------------------------------------------------------

今天的分享就到這里啦,歡迎大家點贊、轉發、留言、拍磚~

下期預告:簡述JS面向對象編程,不見不散~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容