摘要:構(gòu)造函數(shù)繼承遍歷通過對象冒充實現(xiàn)繼承,實際上是在構(gòu)造函數(shù)中,通過獲取父類中的所有屬性,并保存到自身對象中,這樣則可以調(diào)用父類的屬性和方法了。
JS從誕生之初本就不是面向?qū)ο蟮恼Z言。
如何在JS中實現(xiàn)繼承,總結(jié)而言會有四種寫法。
構(gòu)造函數(shù)繼承function Animal(name) { this.name = name this.sayName = function() { console.log(this.name) } } function Dog(name, hobby) { // 遍歷 let ani = new Animal(name) for(let p in ani) { if (ani.hasOwnProperty(p)) { this[p] = ani[p] } } this.hobby = hobby } let dog1 = new Dog("xiaohei", "bone") let dog2 = new Dog("fofo", "bone and fish") console.log(dog1.sayName()) // xiaohei console.log(dog2.sayName()) // fofo
通過對象冒充實現(xiàn)繼承,實際上是在構(gòu)造函數(shù)中,通過獲取父類中的所有屬性,并保存到自身對象中,這樣則可以調(diào)用父類的屬性和方法了。這里forin的方式遍歷父類屬性,因為forin會遍歷公開的屬性和方法,所以通過hasOwnProperty控制寫入當(dāng)前對象的范圍。否則則會將所有屬性全部變?yōu)樗接袑傩浴?/p>
這樣做有一個缺點就是,無法訪問父類中的公開方法和屬性(prototype中的方法)
Animal.prototype.sayHobby = function() { console.log(this.hobby) } dog1.sayHobby() // VM2748:1 Uncaught TypeError: dog1.sayHobby is not a function at:1:6
代碼優(yōu)化
在子類中,既然是需要獲取父類的私有屬性,則可以使用call和apply,當(dāng)調(diào)用父類的方法的時候,改變當(dāng)前上下文為子類對象,則子類對象就可以獲取到了父類的所有私有屬性。
function Animal(name) { this.name = name this.sayName = function() { console.log(this.name) } } function Dog(name, hobby) { // 更改構(gòu)造函數(shù)的上下文 Animal.call(this, name) this.hobby = hobby } let dog1 = new Dog("xiaohei", "bone") let dog2 = new Dog("fofo", "bone and fish") console.log(dog1.sayName()) // xiaohei console.log(dog2.sayName()) // fofo類式繼承
function Animal(name) { this.name = name || "animal" this.types = ["cat", "dog"] this.sayTypes = function() { console.log(this.types.join("-")) } } Animal.prototype.sayName = function() { console.log(this.name) } function Dog(name) { this.name = name } Dog.prototype = new Animal("animal") let dog1 = new Dog("xiaohei") dog1.sayName() // xiaohei let dog2 = new Dog("feifei") dog2.sayName() // feifei
這種繼承方式是通過對子類的prototype.__proto__引用父類的prototype,從而可以讓子類訪問父類中的私有方法和公有方法。詳情可以查看關(guān)鍵字new的實現(xiàn)。
類式繼承會有兩方面的缺點
引用陷阱-子類對象可以隨意修改父類中的方法和變量,并影響其他子類對象
dog1.types.push("fish")
console.log(dog1.types) // ["cat", "dog", "fish"]
console.log(dog2.types) // ["cat", "dog", "fish"]
無法初始化構(gòu)造不同的實例屬性
這個主要是由于類式繼承,是通過Dog.prototype = new Animal("animal")實現(xiàn)的,我們只會調(diào)用一次父類的構(gòu)造函數(shù)。所以只能在子類中從寫父類的屬性,如上的name屬性,在子類中需要重寫一次。
組合繼承組合繼承,即結(jié)合以上兩種繼承方式的優(yōu)點,拋棄兩者的缺點,而實現(xiàn)的一種組合方式
function Animal(name) { this.name = name this.types = ["dog", "cat"] } Animal.prototype.sayName = function() { console.log(this.name) } function Dog(name, hobby) { // 獲取私有方法并調(diào)用父類的構(gòu)造函數(shù),并傳遞構(gòu)造函數(shù)的參數(shù),實現(xiàn)初始化不同的構(gòu)造函數(shù) Animal.call(this, name) this.hobby = hobby } // 子類實例可以訪問父類prototype的方法和屬性 Dog.prototype = new Animal() Dog.prototype.constructor = Dog Dog.prototype.sayHobby = function() { console.log(this.hobby) } // test instance of dog1 let dog1 = new Dog("xiaohei", "bone") dog1.sayName() // xiaohei dog1.sayHobby() // bone dog1.types.push("ant") // types: ["dog", "cat", "ant"] // test instance of dog2 let dog2 = new Dog("feifei", "fish") dog2.sayName() // feifei dog2.sayHobby() // fish dog2.types // ["dog", "cat"]
組合模式,解決了使用構(gòu)造函數(shù)繼承和類式繼承帶來的問題,算是一種比較理想的解決繼承方式,但是這里還有一些瑕疵,調(diào)用了兩次父類(Animal)的構(gòu)造函數(shù)。
所以為了解決這個問題,進(jìn)行了優(yōu)化,產(chǎn)生了
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/101071.html
摘要:可以通過構(gòu)造函數(shù)和原型的方式模擬實現(xiàn)類的功能。原型式繼承與類式繼承類式繼承是在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型的構(gòu)造函數(shù)。寄生式繼承這種繼承方式是把原型式工廠模式結(jié)合起來,目的是為了封裝創(chuàng)建的過程。 js繼承的概念 js里常用的如下兩種繼承方式: 原型鏈繼承(對象間的繼承) 類式繼承(構(gòu)造函數(shù)間的繼承) 由于js不像java那樣是真正面向?qū)ο蟮恼Z言,js是基于對象的,它沒有類的概念。...
摘要:首先為了模擬類創(chuàng)建對象的功能搞出了構(gòu)造函數(shù)。也就是名字膚色膚色這里是繼承里的自有屬性生命值這里繼承的共有屬性的方法攻擊力兵種美國大兵攻擊防御死亡膚色 JS面向?qū)ο笾?【繼承】 我們已經(jīng)準(zhǔn)備了很多前置知識,包括 原型鏈,對象和對象之間的關(guān)系 this,對象和函數(shù)之間的關(guān)系 new, 用函數(shù)批量創(chuàng)建特定的對象的語法糖 JS面向?qū)ο蟮那笆澜裆?我們說,面向?qū)ο笫且环N寫代碼的套路。因為如...
摘要:實現(xiàn)思路使用原型鏈實現(xiàn)對原型方法和方法的繼承,而通過借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承。繼承屬性繼承方法以上代碼,構(gòu)造函數(shù)定義了兩個屬性和。 JS面向?qū)ο蟮某绦蛟O(shè)計之繼承的實現(xiàn)-組合繼承 前言:最近在細(xì)讀Javascript高級程序設(shè)計,對于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯誤,會非常感謝您的指出。文中絕大部分內(nèi)容引用自《Java...
摘要:寄生式繼承的思路與寄生構(gòu)造函數(shù)和工廠模式類似,即創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部已某種方式來增強(qiáng)對象,最后再像真的是它做了所有工作一樣返回對象。 這篇本來應(yīng)該是作為寫JS 面向?qū)ο蟮那白?,只是作為《javascript高級程序設(shè)計》繼承一章的筆記 原型鏈 code 實現(xiàn) function SuperType() { this.colors = [red,blu...
摘要:首先捋清楚類和對象的關(guān)系類比如人類,指的是一個范圍對象比如某個人,指的是這個范圍中具體的對象中的作為構(gòu)造函數(shù)時,就是一個類,通過操作符,可以返回一個對象。 JS中的類與類的繼承 我們知道,JS中沒有類或接口的概念,即不能直接定義抽象的類,也不能直接實現(xiàn)繼承。不過,為了編程的方便,我們可以在 JS 中模擬類和繼承的行為。首先捋清楚類和對象的關(guān)系: 類:比如人類,指的是一個范圍; ...
閱讀 2965·2021-11-17 09:33
閱讀 3753·2021-11-16 11:42
閱讀 3564·2021-10-26 09:50
閱讀 1489·2021-09-22 15:49
閱讀 3106·2021-08-10 09:44
閱讀 3785·2019-08-29 18:36
閱讀 4056·2019-08-29 16:43
閱讀 2330·2019-08-29 14:10