Javascript中的prototype與繼承
通常來(lái)說(shuō),javascript中的對(duì)象就是一個(gè)指向prototype的指針和一個(gè)自身的屬性列表。javascript創(chuàng)建對(duì)象時(shí)采用了寫時(shí)復(fù)制的理念。
只有構(gòu)造器才具有prototype屬性,原型鏈繼承就是創(chuàng)建一個(gè)新的指針,指向構(gòu)造器的prototype屬性。
prototype屬性之所以特別,是因?yàn)閖avascript時(shí)讀取屬性時(shí)的遍歷機(jī)制決定的。本質(zhì)上它就是一個(gè)普通的指針。
構(gòu)造器包括:
1.Object
2.Function
3.Array
4.Date
5.String
下面我們來(lái)舉一些例子吧
//每個(gè)function都有一個(gè)默認(rèn)的屬性prototype,而這個(gè)prototype的constructor默認(rèn)指向這個(gè)函數(shù) //注意Person.constructor 不等于 Person.prototype.constructor. Function實(shí)例自帶constructor屬性 functionPerson(name){ this.name = name; }; Person.prototype.getName =function(){ returnthis.name; }; var p =newPerson("ZhangSan"); console.log(Person.prototype.constructor===Person);// true console.log(p.constructor===Person);// true ,這是因?yàn)閜本身不包含constructor屬性,所以這里其實(shí)調(diào)用的是Person.prototype.constructor
我們的目的是要表示
1. 表明Person繼承自Animal
2. 表明p2是Person的實(shí)例
我們修改一下prototype屬性的指向,讓Person能獲取Animal中的prototype屬性中的方法。也就是Person繼承自Animal(人是野獸)
functionPerson(name){ this.name = name; }; Person.prototype.getName =function(){ returnthis.name; }; var p1 =newPerson("ZhangSan"); console.log(p.constructor===Person);// true console.log(Person.prototype.constructor===Person);// true functionAnimal(){} Person.prototype =newAnimal();//之所以不采用Person.prototype = Animal.prototype,是因?yàn)閚ew 還有其他功能,最后總結(jié)。 var p2 =newPerson("ZhangSan"); //(p2 -> Person.prototype -> Animal.prototype, 所以p2.constructor其實(shí)就是Animal.prototype.constructor) console.log(p2.constructor===Person);// 輸出為false ,但我們的本意是要這里為true的,表明p2是Person的實(shí)例。此時(shí)目的1達(dá)到了,目的2沒(méi)達(dá)到。
但如果我們這么修正
Person.prototype = new Animal(); Person.prototype.constructor = Person;
這時(shí)p2.consturctor是對(duì)了,指向的是Person,表示p2是Person類的實(shí)例,但是新問(wèn)題出現(xiàn)了。此時(shí)目的2達(dá)到了,目的1沒(méi)達(dá)到。
目的1和目的2此時(shí)互相矛盾,是因?yàn)榇藭r(shí)prototype表達(dá)了矛盾的兩個(gè)意思,
1. 表示父類是誰(shuí)
2. 作為自己實(shí)例的原型來(lái)復(fù)制
因此我們不能直接使用prototype屬性來(lái)表示父類是誰(shuí),而是用getPrototypeOf()方法來(lái)知道父類是誰(shuí)。
Person.prototype =newAnimal(); Person.prototype.constructor=Person; var p2 =newPerson("ZhangSan"); p2.constructor//顯示 function Person() {} Object.getPrototypeOf(Person.prototype).constructor//顯示 function Animal() {}
就把這兩個(gè)概念給分開了 ,其實(shí)通過(guò)使用 hasOwnProperty()方法,什么時(shí)候訪問(wèn)的是實(shí)例屬性,什么時(shí)候訪問(wèn)的是原型屬性就一清二楚了
new做了哪些事情?
當(dāng)代碼var p = new Person()執(zhí)行時(shí),new 做了如下幾件事情:
創(chuàng)建一個(gè)空白對(duì)象
創(chuàng)建一個(gè)指向Person.prototype的指針
將這個(gè)對(duì)象通過(guò)this關(guān)鍵字傳遞到構(gòu)造函數(shù)中并執(zhí)行構(gòu)造函數(shù)。
具體點(diǎn)來(lái)說(shuō),在下面這段代碼中,
Person.prototype.getName =function(){}
如果我們通過(guò)
var person =newPerson(); 其實(shí)類似于 var person =newObject(); person.getName =Person.prototype.getName;
因此通過(guò)person.getName()調(diào)用方法時(shí),this指向的是這個(gè)新創(chuàng)建的對(duì)象,而不是prototype對(duì)象。
這其實(shí)在給現(xiàn)有函數(shù)加上新功能的情況下會(huì)用到,我們可以這么擴(kuò)展現(xiàn)有的方法:
//function myFunc 的寫法基本上等于 var myFunc = new Function(); function myFunc (){ } myFunc =function(func){ //可以在這里做點(diǎn)其他事情 returnfunction(){ //可以在這里做點(diǎn)其他事情 return func.apply(this,arguments); } }(myFunc)
也可以在Function.prototype方法里直接通過(guò)this來(lái)訪問(wèn)上面代碼的myFunc所指向的對(duì)象
function myFunc (){ } if(!Function.prototype.extend){ Function.prototype.extend =function(){ var func =this; returnfunction(){ func.apply(this,arguments); } } }; var myFunc = myFunc.extend();
總結(jié)一下
如果采用Person.prototype = Animal.prototype來(lái)表示Person繼承自Animal, instanceof方法也同樣會(huì)顯示p也是Animal的實(shí)例,返回為true.
之所以不采用此方法,是因?yàn)橄旅鎯蓚€(gè)原因:
1.new 創(chuàng)建了一個(gè)新對(duì)象,這樣就避免了設(shè)置Person.prototype.constructor = Person 的時(shí)候也會(huì)導(dǎo)致Animal.prototype.constructor的值變?yōu)镻erson,而是動(dòng)態(tài)給這個(gè)新創(chuàng)建的對(duì)象一個(gè)constructor實(shí)例屬性。這樣實(shí)例上的屬性constructor就覆蓋了Animal.prototype.constructor,這樣Person.prototype.constructor和Animal.prototype.contructor就分開了。
2.Animal自身的this對(duì)象的屬性沒(méi)辦法傳遞給Person
但是像下面這樣直接調(diào)用構(gòu)造函數(shù)又可能失敗,或者產(chǎn)生其他影響。
Person.prototype =newAnimal();
為了避免這種情況,所以我們引入了一個(gè)中間函數(shù)。所以正確的做法應(yīng)該是
Person.prototype =(funtion(){ function F(){}; F.prototype =Animal.prototype returnnew F(); })()
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
- Javascript中 關(guān)于prototype屬性實(shí)現(xiàn)繼承的原理圖
- JavaScript類和繼承 prototype屬性
- js中繼承的幾種用法總結(jié)(apply,call,prototype)
- 深入了解javascript中的prototype與繼承
- javascript prototype的深度探索不是原型繼承那么簡(jiǎn)單
- JavaScript面向?qū)ο笾甈rototypes和繼承
- Javascript 原型和繼承(Prototypes and Inheritance)
- JavaScript不使用prototype和new實(shí)現(xiàn)繼承機(jī)制
- JavaScript使用prototype原型實(shí)現(xiàn)的封裝繼承多態(tài)示例
- javascript基于prototype實(shí)現(xiàn)類似OOP繼承的方法
- JS偽繼承prototype實(shí)現(xiàn)方法示例
- JavaScript使用prototype屬性實(shí)現(xiàn)繼承操作示例
相關(guān)文章
TypeScript工具類 Partial 和 Required 的場(chǎng)景分析
這篇文章主要介紹了TypeScript工具類 Partial 和 Required 的詳細(xì)講解,本文通過(guò)場(chǎng)景描述給大家詳細(xì)講解工具類的使用,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09原生JS實(shí)現(xiàn)圖片輪播與淡入效果的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇原生JS實(shí)現(xiàn)圖片輪播與淡入效果的簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-08-08如何使用ES6的class類繼承來(lái)實(shí)現(xiàn)絢麗小球效果
JS是由ES(ECMAScript)、DOM(瀏覽器文檔對(duì)象)、BOM(瀏覽器對(duì)象模型)組成,這篇文章主要給大家介紹了關(guān)于如何使用ES6的class類繼承來(lái)實(shí)現(xiàn)絢麗小球效果的相關(guān)資料,需要的朋友可以參考下2021-06-06前端頁(yè)面適配之postcss-px-to-viewport實(shí)現(xiàn)步驟
postcss-px-to-viewport是一個(gè)PostCSS插件,它可以將px單位轉(zhuǎn)換為視口單位(vw、vh?或?vmin),這篇文章主要給大家介紹了關(guān)于前端頁(yè)面適配之postcss-px-to-viewport的實(shí)現(xiàn)步驟,需要的朋友可以參考下2024-03-03Bootstrap 附加導(dǎo)航(Affix)插件實(shí)例詳解
附加導(dǎo)航(Affix)插件允許某個(gè) <div> 固定在頁(yè)面的某個(gè)位置。接下來(lái)通過(guò)本文給大家介紹Bootstrap 附加導(dǎo)航(Affix)插件實(shí)例詳解,感興趣的朋友一起看看吧2016-06-06實(shí)現(xiàn)web打印的各種方法介紹及實(shí)現(xiàn)代碼
web的打印方法具我自己懂得知道的有:JQuery插件Jqprint實(shí)現(xiàn);JQery打印插件PrintArea實(shí)現(xiàn)網(wǎng)頁(yè)打印;CSS控制網(wǎng)頁(yè)打印樣式,本文詳細(xì)介紹實(shí)現(xiàn)步驟,感興趣的朋友可以了解下2013-01-01