摘要:而且在超類型的原型中定義的方法,對子類型而言也是不可見的,結(jié)果所有類型都只能使用構(gòu)造函數(shù)模式。在主要考慮對象而不是自定義類型和構(gòu)造函數(shù)的情況下,這個模式也不錯。
寫在前面
注:這個系列是本人對js知識的一些梳理,其中不少內(nèi)容來自書籍:Javascript高級程序設(shè)計第三版和JavaScript權(quán)威指南第六版,感謝它們的作者和譯者。有發(fā)現(xiàn)什么問題的,歡迎留言指出。
1.原型鏈將原型鏈作為實現(xiàn)繼承的方法,基本思想就是利用原型讓一個引用類型繼承另一個引用類型的屬性和方法:
function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function () { return this.property; } function SubType() { this.subproperty = false; } //繼承了SuperType SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function () { return this.subproperty; } var instance = new SubType(); console.log(instance.getSuperValue());//true
原型鏈實現(xiàn)繼承的問題:①問題來自包含引用類型值的原型,因為原來的實例屬性變成現(xiàn)在的原型屬性,會被共享,②在創(chuàng)建子類時,不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。
function SuperType() { this.colors = ["red","blue","green"]; } function SubType() {} //繼承了SuperType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push("black"); console.log(instance1.colors);//["red", "blue", "green", "black"] var instance2 = new SubType(); console.log(instance2.colors);//["red", "blue", "green", "black"]2.借用構(gòu)造函數(shù)
即是在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)(還可以傳遞參數(shù)):
function SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } function SubType() { SuperType.call(this,"jaychou"); } var instance1 = new SubType(); instance1.colors.push("black"); console.log(instance1.colors);//["red", "blue", "green", "black"] console.log(instance1.name);//jaychou var instance2 = new SubType(); console.log(instance2.colors);//["red", "blue", "green"] console.log(instance2.name);//jaychou
借用構(gòu)造函數(shù)的問題:方法都在構(gòu)造函數(shù)中定義,沒有進(jìn)行函數(shù)復(fù)用。而且在超類型的原型中定義的方法,對子類型而言也是不可見的,結(jié)果所有類型都只能使用構(gòu)造函數(shù)模式。考慮到這些問題,借用構(gòu)造函數(shù)的技術(shù)也是很少多帶帶使用的。
3.組合繼承即使用原型鏈實現(xiàn)對原型屬性和方法的繼承,而通過借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承。既通過在原型上定義方法實現(xiàn)了函數(shù)復(fù)用,又能夠保證每個實例都有它自己的屬性:
function SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function () { console.log(this.name); } function SubType(name,age) { //繼承實例屬性 SuperType.call(this,name); this.age = age; } //繼承原型中的方法 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function () { console.log(this.age); } var instance1 = new SubType("jaychou",34); instance1.colors.push("black"); console.log(instance1.colors);//["red", "blue", "green", "black"] instance1.sayName();//jaychou instance1.sayAge();//34 var instance2 = new SubType("xiaoming",15); console.log(instance2.colors);//["red", "blue", "green"] instance2.sayName();//xiaoming instance2.sayAge();//154.原型式繼承
沒有使用嚴(yán)格意義上的構(gòu)造函數(shù),借助原型可以基于已有的對象創(chuàng)建新對象的特點。同時還不必因此創(chuàng)建自定義類型:
function inherit(p) { if(p==null) throw TypeError(); if(Object.create) return Object.create(p); var t = typeof p; if(t !== "object" && t !== "funtion") throw TypeError(); function f() {}; f.prototype = p; return new f(); }
好處:簡單直接方便,只是簡單地想一個對象與另一個對象保持類似的情況下,原型式繼承是很不錯的做法。注意點:包含引用類型值的屬性始終都會共享相應(yīng)的值,就像使用原型模式一樣,如:
var person = { name:"jaychou", friends:[1,2] } var anotherP = inherit(person); anotherP.friends.push(3); console.log(person.friends);//[1, 2, 3] anotherP.name = "xiaoming"; console.log(anotherP.name);//xiaoming console.log(person.name);//jaychou
所以從本質(zhì)上講,原型式繼承就是對傳過來的對象執(zhí)行了一次淺復(fù)制。
5.寄生式繼承即創(chuàng)建一個僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強對象,最后返回對象(接上):
function createAnother(original) { var clone = inherit(original); clone.sayHi = function () { console.log("hi"); } return clone; } var person = { name:"jaychou", friends:[1,2] }; var anotherPerson = createAnother(person); anotherPerson.sayHi();
在例子里給傳進(jìn)來的對象增加了方法sayHi,增強了對象。在主要考慮對象而不是自定義類型和構(gòu)造函數(shù)的情況下,這個模式也不錯。缺點:不能做到函數(shù)復(fù)用而降低效率了。
6.寄生組合式繼承組合繼承的問題就是調(diào)用了兩次超類型構(gòu)造函數(shù):一次是在創(chuàng)建子類型原型的時候,另一次是在子類型構(gòu)造函數(shù)內(nèi)部。解決方案就是:不必為了指定子類型的原型而調(diào)用超類型的構(gòu)造函數(shù),我們所需要的無非就是超類型原型的一個副本而已。本質(zhì)上,就是使用寄生式繼承來繼承超類型的原型,然后再將結(jié)果指定給子類型的原型:
//寄生組合式繼承 function inheritPrototype(subType, superType) { var prototype = inherit(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; } function SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function () { console.log(this.name); } function SubType(name,age) { //借用超類型的構(gòu)造函數(shù)繼承了超類型的實例屬性 SuperType.call(this,name); this.age = age; } //寄生式繼承了超類型的原型方法 inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function () { console.log(this.age); } var instance1 = new SubType("jaychou",34); instance1.sayName();//jaychou instance1.sayAge();//34 console.log(SuperType.prototype.isPrototypeOf(instance1));//true console.log(instance1 instanceof SuperType);//true
好處:①只調(diào)用了一處SuperType構(gòu)造函數(shù),②避免了在SubType.prototype上面創(chuàng)建不必要的、多余的屬性。綜上,寄生組合式繼承是繼承的最理想方式。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/108369.html
摘要:起因構(gòu)造函數(shù)對象字面量都可以用來創(chuàng)建單個對象,但有明顯缺點使用同一個接口創(chuàng)建很多對象,會產(chǎn)生大量的重復(fù)代碼。組合使用構(gòu)造函數(shù)模式和原型模式創(chuàng)建自定義類型的最常見方式,就是組合使用構(gòu)造函數(shù)模式與原型模式。 寫在前面 注:這個系列是本人對js知識的一些梳理,其中不少內(nèi)容來自書籍:Javascript高級程序設(shè)計第三版和JavaScript權(quán)威指南第六版,感謝它們的作者和譯者。有發(fā)現(xiàn)什么問題...
摘要:跨域請求詳解從繁至簡前端掘金什么是為什么要用是的一種使用模式,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題。異步編程入門道典型的面試題前端掘金在界中,開發(fā)人員的需求量一直居高不下。 jsonp 跨域請求詳解——從繁至簡 - 前端 - 掘金什么是jsonp?為什么要用jsonp?JSONP(JSON with Padding)是JSON的一種使用模式,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題...
摘要:引言上篇文章介紹原型,這篇文章接著講繼承,嘔心瀝血之作,大哥們點個贊呀明確一點并不是真正的面向?qū)ο笳Z言,沒有真正的類,所以我們也沒有類繼承實現(xiàn)繼承有且僅有兩種方式,和原型鏈在介紹繼承前我們先介紹下其他概念函數(shù)的三種角色一個函數(shù),有三種角色。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 上篇文章介紹原型,...
摘要:同理,原型鏈也是實現(xiàn)繼承的主要方式的只是語法糖。原型對象也可能擁有原型,并從中繼承方法和屬性,一層一層以此類推。利用構(gòu)造函數(shù)小明張三張三小明缺點每次實例化都需要復(fù)制一遍函數(shù)到實例里面。寄生構(gòu)造函數(shù)模式只有被類出來的才能用。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 最近又攀登了一下JS三座大山中的第二...
摘要:作用域分類作用域共有兩種主要的工作模型。換句話說,作用域鏈?zhǔn)腔谡{(diào)用棧的,而不是代碼中的作用域嵌套。詞法作用域詞法作用域中,又可分為全局作用域,函數(shù)作用域和塊級作用域。 一篇鞏固基礎(chǔ)的文章,也可能是一系列的文章,梳理知識的遺漏點,同時也探究很多理所當(dāng)然的事情背后的原理。 為什么探究基礎(chǔ)?因為你不去面試你就不知道基礎(chǔ)有多重要,或者是說當(dāng)你的工作經(jīng)歷沒有亮點的時候,基礎(chǔ)就是檢驗?zāi)愫脡牡囊豁?..
閱讀 3250·2023-04-25 22:47
閱讀 3765·2021-10-11 10:59
閱讀 2300·2021-09-07 10:12
閱讀 4243·2021-08-11 11:15
閱讀 3432·2019-08-30 13:15
閱讀 1750·2019-08-30 13:00
閱讀 968·2019-08-29 14:02
閱讀 1680·2019-08-26 13:57