摘要:原型鏈上有兩個關鍵詞和比較重要,是設置構造函數的原型對象,是聲明原型的構造函數,不管是對象還是函數,都有一個隱式屬性用來構成一條完整原型鏈的指向。
思考
說到原型,不得不提到原型鏈,js中不管是對象還是方法(也是對象)都有個隱藏屬性_proto_,來表示原型鏈的下一個指向,一般對象是指向Object.prototype,方法是指向Function.prototype,構造函數new出來的對象指向想構造函數的prototype原型鏈的思考
因為原型鏈的存在,當前對象或者方法可以共用原型鏈上的上級屬性和方法
var obj = {}; obj.toString() //[object Object]
obj對象上是沒有toString方法的,因為obj._proto_指向Object.prototype,具體上是調用Object.prototype方法:Object.prototype.toString.apply(obj)
function Foo() { } Foo.toString();//function Foo() {}
方法的原型鏈是Foo->Function.prototype->Object.prototype,所以Foo調用toString方法是引用Function上的toString方法,具體上是調用Function.prototype方法:Function.prototype.toString.apply(obj)
有時候我們為了繼承父類(其實js并沒有類這個概念),會通過原型繼承去繼承父類的一些方法,在此之前,先簡單敘述下通過構造函數實例化一個對象的過程,比如以下創建一個obj對象,
var obj = new Object();
先創建一個空對象{}
空對象{}._proto_指向Object.prototype
Object.apply({})
再執行構造方法里面的代碼
所以當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的構造函數的constructor做一個聲明
Child.prototype.constructor = Child;
因為Child原型是Father實例的一個引用,當想修改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類的原型構造器不用做額外聲明,因為,es6的class的constructor指向自身
繼承的思考子類能使用父類的方法
除了上面提及到的原型鏈繼承,還有例如構造函數繼承:
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
這種方法核心就通過改變構造函數的上下文(context),達到子類能夠使用父類方法,但是這種方法不能使用父類原型方法。
除此之外,還可以遍歷父類實例繼承父類方法:
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
這種方法可以獲取實例能調用的所有方法,除了不可枚舉(ES6 class方法是不可枚舉的)
其實關于繼承js已經有個很好的的實現方法叫寄生組合繼承,大概原理是用構造函數繼承實例屬性,用原型繼承原型方法,而寄生組合繼承是在組合繼承的基礎上強化,兩者的區別是前者避免了兩次實例化父類,是目前比較好的es5實現繼承的方法:
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");總結
????js中有一些構造方法諸如Object、Function、String、Number等等,當當前對象調用方法或獲取屬性時,會順著自身對象到構造函數原型,再到Object原型,最后到Null這么一條原型鏈上查找。原型鏈上有兩個關鍵詞prototype和constructor比較重要,prototype是設置構造函數的原型對象,constructor是聲明原型的構造函數,不管是對象還是函數,都有一個隱式屬性_proto_用來構成一條完整原型鏈的指向。
????繼承有繼承屬性和繼承方法,很多時候es5實現繼承比es6要稍微簡單一點,es6的class的原型方法是不可枚舉的,有時候,掛載方法時需要通過Object.getOwnPropertyNames方法獲取。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/93932.html
摘要:面向對象之二原型鏈對象和對象之間的關系注意這個系列文章要經常站在之父的視角去思考。思考問題我們都知道都屬于那么既然他們都是對象一定有某些相同之處吧對象和對象之間有什么關聯呢如果說你沒有思考過這個問題那么可以換一個更具體的問題。 JS面向對象之二 【原型鏈】(對象和對象之間的關系) 注意這個系列文章,要經常站在JS之父的視角去思考。 牢記我們的需求,我要在JS沒有class的情況下,那么...
摘要:構造函數,實例構造函數,是用來創建對象的函數,本質上也是函數。這里剛好解釋一下時,說到的,可以通過實例的訪問構造函數,但是本質上是原型對象的屬性。 前言 最近在學vue,到周末終于有空寫一些東西了(想想又能騙贊,就有點小激動!)。在javascript基礎中,除了閉包之外,繼承也是一個難點。因為考慮到篇幅較長,所以打算分成兩個部分來寫。同樣基于《javascript高級程序設計》,做一...
摘要:但是,中并沒有類的概念,而是通過構造函數替代了類的功能,為某一類的對象提供共同的屬性和方法。一只名叫的狗,首先繼承了構造函數的原型對象,而的原型對象中的有繼承了函數的原型對象,函數對象中的有繼承了的原型對象。 《圣經》里的第一章創世紀中其中有一段經典記載上帝是如何創造人的。神說:我們要照著我們的形象,按照我們的樣式造人。不謀而合的是,JavaScript中似乎也遵循著上帝的旨意去創造程...
摘要:代碼傳送門如上代碼示例,從其運行結果可知,是等于的原型的,是被對象后返回的函數,從驗證結果來看,函數經過的一層包裝,依然不會影響其原型檢測的綁定。前言 在面向對象語言中,一般都有關鍵字 instanceof 來檢測對象類型,更準確點來說是檢測對象是哪個類型的實例。那么在 JS 中這個關鍵字又有什么不同之處呢?此文僅是一篇對 ES 標準中 instanceof 關鍵字的解讀,并記錄了在此過程中...
摘要:并嘗試用為什么你統計的方式是錯的掘金翻譯自工程師的文章。正如你期望的,文中的前端開發單一職責原則前端掘金單一職責原則又稱單一功能原則,面向對象五個基本原則之一。 單頁式應用性能優化 - 首屏數據漸進式預加載 - 前端 - 掘金前言 針對首頁和部分頁面打開速度慢的問題,我們開始對單頁式應用性能進行優化。本文介紹其中一個方案:基于 HTTP Chunk 的首屏數據漸進式預加載方案,該方案總...
閱讀 3028·2021-11-24 10:21
閱讀 1598·2021-10-11 10:57
閱讀 2813·2021-09-22 15:24
閱讀 2674·2021-09-22 14:58
閱讀 2336·2019-08-30 13:16
閱讀 3487·2019-08-29 13:05
閱讀 3418·2019-08-29 12:14
閱讀 3456·2019-08-27 10:55