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