摘要:面向?qū)ο蟾呒?jí)繼承模式一原型鏈繼承方式原型鏈繼承流程定義父類型構(gòu)造函數(shù)。缺點(diǎn)無(wú)法避免構(gòu)造函數(shù)模式存在的問(wèn)題方法都在構(gòu)造函數(shù)中定義,無(wú)法函數(shù)復(fù)用。六寄生組合式繼承在這里重復(fù)一下組合繼承的代碼組合繼承最大的缺點(diǎn)是會(huì)調(diào)用兩次父構(gòu)造函數(shù)。
JavaScript 面向?qū)ο蟾呒?jí)——繼承模式 一、原型鏈繼承
方式1: 原型鏈繼承
(1)流程:
? 1、定義父類型構(gòu)造函數(shù)。
? 2、給父類型的原型添加方法。
? 3、定義子類型的構(gòu)造函數(shù)。
? 4、創(chuàng)建父類型的對(duì)象賦值給子類型的原型。
? 5、將子類型原型的構(gòu)造屬性設(shè)置為子類型。
? 6、給子類型原型添加方法。
? 7、創(chuàng)建子類型的對(duì)象: 可以調(diào)用父類型的方法。
(2)關(guān)鍵:
子類型的原型為父類型的一個(gè)實(shí)例對(duì)象
// 1.定義父類型構(gòu)造函數(shù) function Supper() { this.supProp = "Supper property" } // 2.給父類型的原型添加方法 Supper.prototype.showSupperProp = function () { console.log(this.supProp) } // 3.定義子類型的構(gòu)造函數(shù) function Sub() { this.subProp = "Sub property" } // 4.子類型的原型為父類型的一個(gè)實(shí)例對(duì)象 Sub.prototype = new Supper() // 5.將子類型原型的構(gòu)造屬性constructor指向子類型 Sub.prototype.constructor = Sub // 6.給子類型原型添加方法 Sub.prototype.showSubProp = function () { console.log(this.subProp) } // 7.創(chuàng)建子類型的對(duì)象,可以調(diào)用父類型的方法 var sub = new Sub() sub.showSupperProp() // Supper property sub.showSubProp() // Sub property console.log(sub) // Sub
(3)缺點(diǎn):
1、包含引用類型值的原型,由于實(shí)例共享屬性,一個(gè)實(shí)例對(duì)原型屬性的修改會(huì)在另一個(gè)實(shí)例中反映出來(lái)。
2、不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。
二、借用構(gòu)造函數(shù)繼承方式2: 借用構(gòu)造函數(shù)繼承。
(1)流程:
? 1、定義父類型構(gòu)造函數(shù)。
? 2、定義子類型構(gòu)造函數(shù)。
? 3、在子類型構(gòu)造函數(shù)中調(diào)用父類型構(gòu)造。
// 1.定義父類型構(gòu)造函數(shù) function Person(name, age) { this.name = name this.age = age } // 2.定義子類型構(gòu)造函數(shù) function Student(name, age, price) { // 3.在子類型構(gòu)造函數(shù)中調(diào)用父類型構(gòu)造 Person.call(this, name, age) // 相當(dāng)于: this.Person(name, age) /*this.name = name this.age = age*/ this.price = price } var s = new Student("Tom", 20, 14000) console.log(s.name, s.age, s.price) // Tom 20 14000
(2)關(guān)鍵:
在子類型構(gòu)造函數(shù)中通過(guò)call()調(diào)用父類型構(gòu)造函數(shù)。
(3)缺點(diǎn):
1、無(wú)法避免構(gòu)造函數(shù)模式存在的問(wèn)題——方法都在構(gòu)造函數(shù)中定義,無(wú)法函數(shù)復(fù)用。
2、在父類型原型中定義的方法在子類型中是不可見的,只能繼承父類型構(gòu)造函數(shù)中定義的屬性和方法。
三、組合繼承方式3: 原型鏈+借用構(gòu)造函數(shù)的組合繼承。
1、利用原型鏈實(shí)現(xiàn)對(duì)父類型對(duì)象的方法繼承。
2、利用call()借用父類型構(gòu)造函數(shù)初始化相同屬性。
function Person(name, age) { this.name = name this.age = age } Person.prototype.setName = function (name) { this.name = name } function Student(name, age, price) { Person.call(this, name, age) // 為了得到屬性 this.price = price } Student.prototype = new Person() // 為了能看到父類型的方法 Student.prototype.constructor = Student //修正constructor屬性 Student.prototype.setPrice = function (price) { this.price = price } var s = new Student("Tom", 24, 15000) s.setName("Bob") s.setPrice(16000) console.log(s.name, s.age, s.price)四、原型式繼承
function createObj(o) { function F(){} F.prototype = o; return new F(); }
就是 ES5 Object.create 的模擬實(shí)現(xiàn),將傳入的對(duì)象作為創(chuàng)建的對(duì)象的原型。
缺點(diǎn):包含引用類型的屬性值始終都會(huì)共享相應(yīng)的值,這點(diǎn)跟原型鏈繼承一樣。
var person = { name: "kevin", friends: ["daisy", "kelly"] } var person1 = createObj(person); var person2 = createObj(person); person1.name = "person1"; console.log(person2.name); // kevin person1.firends.push("taylor"); console.log(person2.friends); // ["daisy", "kelly", "taylor"]
注意:修改person1.name的值,person2.name的值并未發(fā)生改變,并不是因?yàn)?b>person1和person2有獨(dú)立的 name 值,而是因?yàn)?b>person1.name = "person1",給person1添加了 name 值,并非修改了原型上的 name 值。
五、寄生式繼承創(chuàng)建一個(gè)僅用于封裝繼承過(guò)程的函數(shù),該函數(shù)在內(nèi)部以某種形式來(lái)做增強(qiáng)對(duì)象,最后返回對(duì)象。
function createObj (o) { var clone = Object.create(o); clone.sayName = function () { console.log("hi"); } return clone; }
缺點(diǎn):跟借用構(gòu)造函數(shù)模式一樣,每次創(chuàng)建對(duì)象都會(huì)創(chuàng)建一遍方法。
六、寄生組合式繼承在這里重復(fù)一下組合繼承的代碼:
function Parent (name) { this.name = name; this.colors = ["red", "blue", "green"]; } Parent.prototype.getName = function () { console.log(this.name) } function Child (name, age) { Parent.call(this, name); this.age = age; } Child.prototype = new Parent(); var child1 = new Child("kevin", "18"); console.log(child1)
組合繼承最大的缺點(diǎn)是會(huì)調(diào)用兩次父構(gòu)造函數(shù)。
一次是設(shè)置子類型實(shí)例的原型的時(shí)候:
Child.prototype = new Parent();
一次在創(chuàng)建子類型實(shí)例的時(shí)候:
var child1 = new Child("kevin", "18");
回想下 new 的模擬實(shí)現(xiàn),其實(shí)在這句中,我們會(huì)執(zhí)行:
Parent.call(this, name);
在這里,我們又會(huì)調(diào)用了一次 Parent 構(gòu)造函數(shù)。
所以,在這個(gè)例子中,如果我們打印 child1 對(duì)象,我們會(huì)發(fā)現(xiàn) Child.prototype 和 child1 都有一個(gè)屬性為colors,屬性值為["red", "blue", "green"]。
那么我們?cè)撊绾尉媲缶苊膺@一次重復(fù)調(diào)用呢?
如果我們不使用 Child.prototype = new Parent() ,而是間接的讓 Child.prototype 訪問(wèn)到 Parent.prototype 呢?
看看如何實(shí)現(xiàn):
function Parent (name) { this.name = name; this.colors = ["red", "blue", "green"]; } Parent.prototype.getName = function () { console.log(this.name) } function Child (name, age) { Parent.call(this, name); this.age = age; } // 關(guān)鍵的三步 var F = function () {}; F.prototype = Parent.prototype; Child.prototype = new F(); var child1 = new Child("kevin", "18"); console.log(child1);
最后我們封裝一下這個(gè)繼承方法:
function object(o) { function F() {} F.prototype = o; return new F(); } function prototype(child, parent) { var prototype = object(parent.prototype); prototype.constructor = child; child.prototype = prototype; } // 當(dāng)我們使用的時(shí)候: prototype(Child, Parent);
引用《JavaScript高級(jí)程序設(shè)計(jì)》中對(duì)寄生組合式繼承的夸贊就是:
這種方式的高效率體現(xiàn)它只調(diào)用了一次 Parent 構(gòu)造函數(shù),并且因此避免了在 Parent.prototype 上面創(chuàng)建不必要的、多余的屬性。與此同時(shí),原型鏈還能保持不變;因此,還能夠正常使用 instanceof 和 isPrototypeOf。開發(fā)人員普遍認(rèn)為寄生組合式繼承是引用類型最理想的繼承范式。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/105094.html
摘要:類類的概念應(yīng)該是面向?qū)ο笳Z(yǔ)言的一個(gè)特色,但是并不像,等高級(jí)語(yǔ)言那樣擁有正式的類,而是多數(shù)通過(guò)構(gòu)造器以及原型方式來(lái)仿造實(shí)現(xiàn)。因此,出現(xiàn)了構(gòu)造函數(shù)方式,它的關(guān)鍵在于構(gòu)造器概念的引入。于是,這就產(chǎn)生了構(gòu)造函數(shù)原型法的類構(gòu)造方法。 類 Class 類的概念應(yīng)該是面向?qū)ο笳Z(yǔ)言的一個(gè)特色,但是JavaScript并不像Java,C++等高級(jí)語(yǔ)言那樣擁有正式的類,而是多數(shù)通過(guò)構(gòu)造器以及原型方式...
摘要:實(shí)現(xiàn)思路使用原型鏈實(shí)現(xiàn)對(duì)原型方法和方法的繼承,而通過(guò)借用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。繼承屬性繼承方法以上代碼,構(gòu)造函數(shù)定義了兩個(gè)屬性和。 JS面向?qū)ο蟮某绦蛟O(shè)計(jì)之繼承的實(shí)現(xiàn)-組合繼承 前言:最近在細(xì)讀Javascript高級(jí)程序設(shè)計(jì),對(duì)于我而言,中文版,書中很多地方翻譯的差強(qiáng)人意,所以用自己所理解的,嘗試解讀下。如有紕漏或錯(cuò)誤,會(huì)非常感謝您的指出。文中絕大部分內(nèi)容引用自《Java...
摘要:構(gòu)造函數(shù)模式這種方法創(chuàng)建自定義的構(gòu)造函數(shù),從而自定義對(duì)象類型的屬性和方法。借用構(gòu)造函數(shù)在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù),通過(guò)和方法來(lái)實(shí)現(xiàn)。 JavaScript中沒有類的概念,它不是嚴(yán)格意義上的面向?qū)ο笳Z(yǔ)言,而是基于對(duì)象(Object-based)的編程語(yǔ)言。下面是讀《JavaScript高級(jí)程序設(shè)計(jì)(第三版)》的學(xué)習(xí)筆記,總結(jié)一些常用的創(chuàng)建對(duì)象和繼承的方法。 一、創(chuàng)建對(duì)象 1...
摘要:無(wú)限增殖返回蘋果返回香蕉返回返回使用的新語(yǔ)法方法會(huì)創(chuàng)建一個(gè)新對(duì)象,使用現(xiàn)有的對(duì)象來(lái)提供新創(chuàng)建的對(duì)象的。是新增的,用來(lái)規(guī)范原型式繼承。這里將返回的新對(duì)象放到子類的原型對(duì)象里面,這樣子類就擁有了父類的原型對(duì)象,也就實(shí)現(xiàn)了方法的繼承。 這是最后的最后了,我會(huì)順便總結(jié)一下各種繼承方式的學(xué)習(xí)和理解。(老板要求什么的,管他呢) 一、繼承-組合繼承、偽經(jīng)典繼承 showImg(https://seg...
摘要:請(qǐng)記住,這些書中的一些可能不是最新的,但概念和基礎(chǔ)仍應(yīng)適用。是最好的老師之一。的秘密由部分組成。在你完成這些書后,查看書籍和最好的本土?xí)? 我看過(guò)三本,第1本,第二本,第四本。第一本買的的實(shí)體書,其他兩本看的是電子書。第一本是大名鼎鼎老道寫的,書很薄,但是非常經(jīng)典。javascirpt忍者秘籍是jquery的作者寫的,也是非常經(jīng)典。you dont kown js系列也是非常好。看了...
閱讀 3938·2021-11-18 13:19
閱讀 1181·2021-10-11 10:58
閱讀 3291·2019-08-29 16:39
閱讀 3142·2019-08-26 12:08
閱讀 2036·2019-08-26 11:33
閱讀 2460·2019-08-23 18:30
閱讀 1309·2019-08-23 18:21
閱讀 2522·2019-08-23 18:18