大家好淳蔼,我是IT修真院深圳分院第01期學(xué)員坷襟,一枚正直純潔善良的web程序員乡范。
今天給大家分享一下配名,修真院官網(wǎng)JS(職業(yè))任務(wù)4,深度思考中的知識點——JS原型鏈和訪問對象原型的方法
1.介紹
JavaScript 中晋辆,萬物皆對象渠脉。JavaScript根據(jù)"原型鏈"(prototype chain)模式,來實現(xiàn)繼承瓶佳。
2.涉及
2.1對象
JavaScript中芋膘,對象是有區(qū)別的,分為普通對象和函數(shù)對象霸饲,Object 为朋,F(xiàn)unction 是JS自帶的函數(shù)對象,function定義方式本質(zhì)上還是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习寸,做了簡化設(shè)計,將new命令引入JavaScript中傻工,new后面跟對象的構(gòu)造函數(shù)融涣,用來創(chuàng)建對象童番。這樣做有個缺點:無法共享方法和屬性。
比如威鹿,在DOG對象的構(gòu)造函數(shù)中剃斧,設(shè)置一個實例對象的共有屬性species。
function DOG(name){
this.name = name;
this.species = '犬科';
}
然后忽你,生成兩個實例對象:
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
這兩個對象的species屬性是獨立的幼东,修改其中一個,不會影響到另一個科雳。
dogA.species = '貓科';
alert(dogB.species); // 顯示"犬科"根蟹,不受dogA的影響
每一個實例對象,都有自己的屬性和方法的副本糟秘。這不僅無法做到數(shù)據(jù)共享简逮,也是極大的資源浪費。
Brendan Eich決定為構(gòu)造函數(shù)設(shè)置一個prototype屬性尿赚。這個屬性包含一個對象散庶,所有實例對象需要共享的屬性和方法,都放在這個對象里面凌净;那些不需要共享的屬性和方法悲龟,就放在構(gòu)造函數(shù)里面。實例對象一旦創(chuàng)建冰寻,將自動引用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 中贪庙,每當(dāng)定義一個對象(函數(shù))時候蜘犁,對象中都會包含一些預(yù)定義的屬性。其中函數(shù)對象的一個屬性就是原型對象 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在創(chuàng)建對象(不論是普通對象還是函數(shù)對象)的時候奏窑,都有一個叫做__proto__的內(nèi)置屬性,用于指向創(chuàng)建它的函數(shù)對象的原型對象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__屬性,它指向創(chuàng)建它的函數(shù)對象(Object)的prototype
console.log(person.prototype.__proto__ === Object.prototype) //true
繼續(xù)鹰晨,Object.prototype對象也有__proto__屬性墨叛,但它比較特殊,為null
console.log(Object.prototype.__proto__) //null
我們把這個有__proto__串起來的直到Object.prototype.__proto__為null的鏈叫做原型鏈模蜡。
2.5 constructor屬性
prototype對象有一個constructor屬性漠趁,默認指向prototype對象所在的構(gòu)造函數(shù)。
由于constructor屬性定義在prototype對象上面忍疾,意味著可以被所有實例對象繼承闯传。
constructor屬性的作用,是分辨原型對象到底屬于哪個構(gòu)造函數(shù)卤妒。
2.6 總結(jié)
1.原型和原型鏈?zhǔn)荍S實現(xiàn)繼承的一種模型甥绿。
2.原型鏈的形成是真正是靠__proto__ 而非prototype。
3.常見問題
訪問對象原型的方法有哪些荚孵?
4.解決方法
獲取實例對象obj的原型對象妹窖,有三種方法:
1. obj.__proto__
2. obj.constructor.prototype
3. Object.getPrototypeOf(obj)
上面三種方法之中纬朝,前兩種都不是很可靠收叶。最新的ES6標(biāo)準(zhǔn)規(guī)定,__proto__屬性只有瀏覽器才需要部署共苛,其他環(huán)境可以不部署判没。而obj.constructor.prototype在手動改變原型對象時,可能會失效隅茎。
5.編碼實戰(zhàn)
6.擴展思考
1.Object.__proto__ === Function.prototype // true
2.Function.__proto__ === Function.prototype // true
3.Function.prototype.__proto__ === Object.prototype //true
1.Object是函數(shù)對象澄峰,是通過new Function()創(chuàng)建,所以O(shè)bject.__proto__指向Function.prototype辟犀。
2.Function 也是對象函數(shù)俏竞,也是通過new Function()創(chuàng)建,所以Function.__proto__指向Function.prototype堂竟。
3.Function.prototype是個函數(shù)對象魂毁,理論上其__proto__應(yīng)該指向 Function.prototype,就是它自己出嘹,自己指向自己席楚,沒有意義。函數(shù)對象也是對象税稼,給它設(shè)定根指向Object.prototype烦秩,Object.prototype.__proto__ === null垮斯,保證原型鏈能夠正常結(jié)束。
7.參考文獻
參考一:阮一峰:Javascript繼承機制的設(shè)計思想
參考二:zhangjiahao8961:JavaScript原型及原型鏈詳解
8.更多討論
JavaScript 對象的繼承機制
鳴謝
感謝大家觀看
視頻鏈接
------------------------------------------------------------------------------------------------------------------------
今天的分享就到這里啦只祠,歡迎大家點贊兜蠕、轉(zhuǎn)發(fā)、留言抛寝、拍磚~
下期預(yù)告:簡述JS面向?qū)ο缶幊涛保灰姴簧