摘要:原型鏈上有兩個關(guān)鍵詞和比較重要,是設(shè)置構(gòu)造函數(shù)的原型對象,是聲明原型的構(gòu)造函數(shù),不管是對象還是函數(shù),都有一個隱式屬性用來構(gòu)成一條完整原型鏈的指向。
思考
說到原型,不得不提到原型鏈,js中不管是對象還是方法(也是對象)都有個隱藏屬性_proto_,來表示原型鏈的下一個指向,一般對象是指向Object.prototype,方法是指向Function.prototype,構(gòu)造函數(shù)new出來的對象指向想構(gòu)造函數(shù)的prototype原型鏈的思考
因為原型鏈的存在,當(dāng)前對象或者方法可以共用原型鏈上的上級屬性和方法
var obj = {}; obj.toString() //[object Object]
obj對象上是沒有toString方法的,因為obj._proto_指向Object.prototype,具體上是調(diào)用Object.prototype方法:Object.prototype.toString.apply(obj)
function Foo() { } Foo.toString();//function Foo() {}
方法的原型鏈?zhǔn)荈oo->Function.prototype->Object.prototype,所以Foo調(diào)用toString方法是引用Function上的toString方法,具體上是調(diào)用Function.prototype方法:Function.prototype.toString.apply(obj)
有時候我們?yōu)榱死^承父類(其實js并沒有類這個概念),會通過原型繼承去繼承父類的一些方法,在此之前,先簡單敘述下通過構(gòu)造函數(shù)實例化一個對象的過程,比如以下創(chuàng)建一個obj對象,
var obj = new Object();
先創(chuàng)建一個空對象{}
空對象{}._proto_指向Object.prototype
Object.apply({})
再執(zhí)行構(gòu)造方法里面的代碼
所以當(dāng)es5繼承方法時,可以選擇原型繼承,通過修改prototype的值,如:
ES5的情況:
var Father = function(name) { this.name = name; } Father.prototype.say = function() { return "my name is " + this.name; } var Child = function(name) { this.name = name; } Child.prototype = new Father(); var child = new Child("Nico"); child.say();//my name is Nico
但是在上面原型繼承的情況,我們還要對Child的構(gòu)造函數(shù)的constructor做一個聲明
Child.prototype.constructor = Child;
因為Child原型是Father實例的一個引用,當(dāng)想修改Child原型的方法時,會被掛在Father的實例對象上。
ES6的情況:
class Father { constructor(name) { this.name = name; } say() { return "my name is " + this.name; } } class Child extends Father { constructor(name) { super(name) } } var child = new Child("Nico"); child.say()//my name is Nico
es6的class類中,Child類的原型構(gòu)造器不用做額外聲明,因為,es6的class的constructor指向自身
繼承的思考子類能使用父類的方法
除了上面提及到的原型鏈繼承,還有例如構(gòu)造函數(shù)繼承:
function Veticle(name) { this.name = name || null this.drive = function() { console.log(this.name + " drives! --from Veticle "); } } function Car(name) { Veticle.call(this) this.name = name; } var car = new Car("a car"); car.drive();//a car drives! --from Veticle
這種方法核心就通過改變構(gòu)造函數(shù)的上下文(context),達(dá)到子類能夠使用父類方法,但是這種方法不能使用父類原型方法。
除此之外,還可以遍歷父類實例繼承父類方法:
function Veticle(name) { this.name = name || null this.drive = function() { console.log(this.name + "drives! --from Veticle "); } } Veticle.prototype.getName = function() { return this.name; } function Car(name) { var veticle = new Veticle(); for (var p in veticle) { console.log(p) Car.prototype[p] = veticle[p]; } this.name = name; } var car = new Car("a car"); car.getName();//a car
這種方法可以獲取實例能調(diào)用的所有方法,除了不可枚舉(ES6 class方法是不可枚舉的)
其實關(guān)于繼承js已經(jīng)有個很好的的實現(xiàn)方法叫寄生組合繼承,大概原理是用構(gòu)造函數(shù)繼承實例屬性,用原型繼承原型方法,而寄生組合繼承是在組合繼承的基礎(chǔ)上強(qiáng)化,兩者的區(qū)別是前者避免了兩次實例化父類,是目前比較好的es5實現(xiàn)繼承的方法:
function Veticle(name) { this.name = name || null this.drive = function() { console.log(this.name + "drives! --from Veticle "); } } Veticle.prototype.getName = function() { return this.name; } function Car(name) { Veticle.call(this) this.name = name || "car" } function inheritProto(subType, superType) { var prototype = Object.create(superType.prototype); subType.prototype.constructor = subType; subType.prototype = prototype; } inheritProto(Car, Veticle) var car = new Car("siip");總結(jié)
????js中有一些構(gòu)造方法諸如Object、Function、String、Number等等,當(dāng)當(dāng)前對象調(diào)用方法或獲取屬性時,會順著自身對象到構(gòu)造函數(shù)原型,再到Object原型,最后到Null這么一條原型鏈上查找。原型鏈上有兩個關(guān)鍵詞prototype和constructor比較重要,prototype是設(shè)置構(gòu)造函數(shù)的原型對象,constructor是聲明原型的構(gòu)造函數(shù),不管是對象還是函數(shù),都有一個隱式屬性_proto_用來構(gòu)成一條完整原型鏈的指向。
????繼承有繼承屬性和繼承方法,很多時候es5實現(xiàn)繼承比es6要稍微簡單一點,es6的class的原型方法是不可枚舉的,有時候,掛載方法時需要通過Object.getOwnPropertyNames方法獲取。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/93932.html
摘要:面向?qū)ο笾玩湆ο蠛蛯ο笾g的關(guān)系注意這個系列文章要經(jīng)常站在之父的視角去思考。思考問題我們都知道都屬于那么既然他們都是對象一定有某些相同之處吧對象和對象之間有什么關(guān)聯(lián)呢如果說你沒有思考過這個問題那么可以換一個更具體的問題。 JS面向?qū)ο笾?【原型鏈】(對象和對象之間的關(guān)系) 注意這個系列文章,要經(jīng)常站在JS之父的視角去思考。 牢記我們的需求,我要在JS沒有class的情況下,那么...
摘要:構(gòu)造函數(shù),實例構(gòu)造函數(shù),是用來創(chuàng)建對象的函數(shù),本質(zhì)上也是函數(shù)。這里剛好解釋一下時,說到的,可以通過實例的訪問構(gòu)造函數(shù),但是本質(zhì)上是原型對象的屬性。 前言 最近在學(xué)vue,到周末終于有空寫一些東西了(想想又能騙贊,就有點小激動!)。在javascript基礎(chǔ)中,除了閉包之外,繼承也是一個難點。因為考慮到篇幅較長,所以打算分成兩個部分來寫。同樣基于《javascript高級程序設(shè)計》,做一...
摘要:但是,中并沒有類的概念,而是通過構(gòu)造函數(shù)替代了類的功能,為某一類的對象提供共同的屬性和方法。一只名叫的狗,首先繼承了構(gòu)造函數(shù)的原型對象,而的原型對象中的有繼承了函數(shù)的原型對象,函數(shù)對象中的有繼承了的原型對象。 《圣經(jīng)》里的第一章創(chuàng)世紀(jì)中其中有一段經(jīng)典記載上帝是如何創(chuàng)造人的。神說:我們要照著我們的形象,按照我們的樣式造人。不謀而合的是,JavaScript中似乎也遵循著上帝的旨意去創(chuàng)造程...
摘要:代碼傳送門如上代碼示例,從其運(yùn)行結(jié)果可知,是等于的原型的,是被對象后返回的函數(shù),從驗證結(jié)果來看,函數(shù)經(jīng)過的一層包裝,依然不會影響其原型檢測的綁定。前言 在面向?qū)ο笳Z言中,一般都有關(guān)鍵字 instanceof 來檢測對象類型,更準(zhǔn)確點來說是檢測對象是哪個類型的實例。那么在 JS 中這個關(guān)鍵字又有什么不同之處呢?此文僅是一篇對 ES 標(biāo)準(zhǔn)中 instanceof 關(guān)鍵字的解讀,并記錄了在此過程中...
摘要:并嘗試用為什么你統(tǒng)計的方式是錯的掘金翻譯自工程師的文章。正如你期望的,文中的前端開發(fā)單一職責(zé)原則前端掘金單一職責(zé)原則又稱單一功能原則,面向?qū)ο笪鍌€基本原則之一。 單頁式應(yīng)用性能優(yōu)化 - 首屏數(shù)據(jù)漸進(jìn)式預(yù)加載 - 前端 - 掘金前言 針對首頁和部分頁面打開速度慢的問題,我們開始對單頁式應(yīng)用性能進(jìn)行優(yōu)化。本文介紹其中一個方案:基于 HTTP Chunk 的首屏數(shù)據(jù)漸進(jìn)式預(yù)加載方案,該方案總...
閱讀 3019·2021-11-24 10:21
閱讀 1588·2021-10-11 10:57
閱讀 2804·2021-09-22 15:24
閱讀 2659·2021-09-22 14:58
閱讀 2331·2019-08-30 13:16
閱讀 3478·2019-08-29 13:05
閱讀 3411·2019-08-29 12:14
閱讀 3441·2019-08-27 10:55