學(xué)習(xí)javascript面向?qū)ο?javascript實(shí)現(xiàn)繼承的方式
本文實(shí)例為大家介紹了javascript實(shí)現(xiàn)繼承的6種方式,分享給大家供大家參考,具體內(nèi)容如下
1、【原型鏈繼承】實(shí)現(xiàn)的本質(zhì)是重寫原型對(duì)象,代之以一個(gè)新類型的實(shí)例。實(shí)際上不是SubType的原型的constructor屬性被重寫了,而是SubType的原型指向了另一個(gè)對(duì)象——SuperType的原型,而這個(gè)原型對(duì)象的construtor屬性指向的是SuperType
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(); alert(instance.getSuperValue());//true
[注意1]謹(jǐ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; } //重寫超類型的方法 SubType.prototype.getSuperValue = function(){ return false; } var instance = new SubType(); alert(instance.getSuperValue());//false
[注意2]通過原型鏈實(shí)現(xiàn)繼承時(shí),不能使用對(duì)象字面量創(chuàng)建原型方法,這樣做會(huì)重寫原型鏈
function SuperType(){ this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false; } //繼承了SuperType SubType.prototype = new SuperType(); //使用字面量方法添加新方法會(huì)導(dǎo)致上一行代碼無效 SubType.prototype = { getSubValue : function(){ return this,subproperty; }, someOtherMethod : function(){ return false; } }; var instance = new SubType(); alert(instance.getSuperValue());//error
[缺點(diǎn)1]在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)
[缺點(diǎn)2]包含引用類型值的原型屬性會(huì)被所有實(shí)例共享
function SuperType(){ this.colors = ['red','blue','green']; } function SubType(){} //繼承了SuperType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push('black'); alert(instance1.colors);//'red,blue,green,black' var instance2 = new SubType(); alert(instance2.colors);//'red,blue,green,black'
2、【借用構(gòu)造函數(shù)繼承(又叫偽造對(duì)象或經(jīng)典繼承)】在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù),因此通過使用apply()和call()方法也可以在將來新創(chuàng)建的對(duì)象上執(zhí)行構(gòu)造函數(shù)
function SuperType(){ this.colors = ['red','blue','green']; } function SubType(){ //繼承了SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push('black'); alert(instance1.colors);//'red,blue,green,black' var instance2 = new SubType(); alert(instance2.colors);//'red,blue,green'
[優(yōu)點(diǎn)]傳遞參數(shù)
function SuperType(name){ this.name = name; } function SubType(){ //繼承了SUperType,同時(shí)還傳遞了參數(shù) SuperType.call(this,"Nicholas"); //實(shí)例屬性 this.age = 29; } var instance = new SubType(); alert(instance.name);//"Nicholas" alert(instance.age);//29
[注意]為了確保SuperType構(gòu)造函數(shù)不會(huì)重寫子類型的屬性,可以在調(diào)用超類型構(gòu)造函數(shù)后,再添加應(yīng)該在子類型中定義的屬性
function SuperType(name){ this.name = name; this.age = 30; } function SubType(){ //實(shí)例屬性 this.age = 29; //繼承了SUperType,同時(shí)還傳遞了參數(shù) SuperType.call(this,"Nicholas"); } var instance = new SubType(); //實(shí)例屬性被重寫為SuperType構(gòu)造函數(shù)的屬性 alert(instance.age);//30
[缺點(diǎn)1]無法實(shí)現(xiàn)函數(shù)復(fù)用
[缺點(diǎn)2]在超類型的原型中定義的方法,對(duì)子類型而言也是不可見的,結(jié)果所有類型都只能使用構(gòu)造函數(shù)模式
3、【組合繼承(又叫偽經(jīng)典繼承)】將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一起,從而發(fā)揮二者之長(zhǎng)的一種繼承模式。其背后的思路是使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,而通過借用構(gòu)造函數(shù)來實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。這樣,既通過在原型上定義方法實(shí)現(xiàn)了函數(shù)復(fù)用,又能夠保證每個(gè)實(shí)例都有它自己的屬性,成為JavaScript中最常用的繼承模式。
function SuperType(name){ this.name = name; this.colors = ['red','blue','green']; } SuperType.prototype.sayName = function(){ alert(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(){ alert(this.age); } var instance1 = new SubType("Nicholas",29); instance1.colors.push("black"); alert(instance1.colors);//'red,blue,green,black' instance1.sayName();//"Nicholas" instance1.sayAge();//29 var instance2 = new SubType("Greg",27); alert(instance2.colors);//'red,blue,green' instance2.sayName();//"Greg" instance2.sayAge();//27
[缺點(diǎn)]無論什么情況下,都會(huì)調(diào)用兩次超類型構(gòu)造函數(shù):一次是在創(chuàng)建子類型原型的時(shí)候,另一次是在子類型構(gòu)造函數(shù)內(nèi)部。子類型最終會(huì)包含超類型對(duì)象的全部實(shí)例屬性,但不得不在調(diào)用子類型構(gòu)造函數(shù)時(shí)重寫這些屬性。
function SuperType(name){ this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name,age){ SuperType.call(this,name); // 第二次調(diào)用SuperType() this.age = age; } SubType.prototype = new SuperType(); //第一次調(diào)用SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); };
4、【原型式繼承】借助原型可以基于已有的對(duì)象創(chuàng)建新對(duì)象,同時(shí)還不必因此創(chuàng)建自定義類型。從本質(zhì)上講,object()對(duì)傳入其中的對(duì)象執(zhí)行了一次淺復(fù)制。
[注意]原型式繼承要求必須有一個(gè)對(duì)象可以作為另一個(gè)對(duì)象的基礎(chǔ),如果有這么一個(gè)對(duì)象的話,可以把它傳遞給object()函數(shù),然后再根據(jù)具體需求對(duì)得到的對(duì)象加以修改即可
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Nicholas", friends: ["Shelby","Court","Van"] }; var anotherPerson = object(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"
【4.1】【Object.create()方法】:ECMAScript5新增Object.create()方法規(guī)范化了原型式繼承。這個(gè)方法接收兩個(gè)參數(shù):一個(gè)用作新對(duì)象原型的對(duì)象和(可選的)一個(gè)為新對(duì)象定義額外屬性的對(duì)象。在傳入一個(gè)參數(shù)情況下,Object.create()與object()方法的行為相同
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Nicholas", friends:["Shelby","Court","Van"] }; var anotherPerson = Object.create(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"
[注意]Object.create()方法的第二個(gè)參數(shù)與Object.defineProperties()方法的第二個(gè)參數(shù)格式相同:每個(gè)屬性都是通過自己的描述符定義的。以這種方式指定的任何屬性都會(huì)覆蓋原型對(duì)象上的同名屬性。
var person = { name: "Nicholas", friends:["Shelby","Court","Van"] }; var anotherPerson = Object.create(person,{ name: { value: "Greg" } }); alert(anotherPerson.name);//"Greg"
【4.2】低版本瀏覽器下兼容Object.create()方法
if(typeof Object.create != "function"){ (function(){ var F = function(){}; Object.create = function(o){ if(arguments.length > 1){ throw Error('Second argument noe supported'); } if(o === null){ throw Error("Cannot set a null [[Prototype]]"); } if(typeof o != 'Object'){ throw TypeError("Arguments must be an object"); } F.prototype = o; return new F(); } })(); }
5、【寄生式繼承】創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù),該函數(shù)在內(nèi)部以某種方式來增強(qiáng)對(duì)象,最后再像真的是它做了所有工作一樣返回對(duì)象
[缺點(diǎn)]無法實(shí)現(xiàn)函數(shù)復(fù)用
function object(o){ function F(){}; F.prototype = o; return new F(); } function createAnother(original){ var clone = object(original);//通過調(diào)用函數(shù)創(chuàng)建一個(gè)新對(duì)象 clone.sayHi = function(){ //以某種方式來增強(qiáng)這個(gè)對(duì)象 alert("hi"); }; return clone;//返回這個(gè)對(duì)象 } var person = { name: "Nicholas", friends: ["Shelby","Court","Van"] }; var anotherPerson = createAnother(person); anotherPerson.sayHi();//"hi"
6、【寄生組合式繼承】通過借用構(gòu)造函數(shù)來繼承屬性,通過原型鏈的混成形式來繼承方法。其背后的基本思路是:不必為了指定子類型的原型而調(diào)用超類型的構(gòu)造函數(shù),所需的無非就是超類型原型的一個(gè)副本而已。本質(zhì)上,就是使用寄生式繼承來繼承超類型的原型,然后再將結(jié)果指定給子類型的原型。寄生組合式繼承是引用類型最理想的繼承范式。
//這個(gè)例子中的高效率體現(xiàn)在它只調(diào)用了一次Super構(gòu)造函數(shù),并且因此避免了在SubType.prototype上面創(chuàng)建不必要的、多余的屬性。與此同時(shí),原型鏈還能保持不變。 function object(o){ function F(){}; F.prototype = o; return new F(); } function inheritPrototype(subType,superType){ var prototype = object(superType.prototype);//創(chuàng)建對(duì)象 prototype.constructor = subType;//增強(qiáng)對(duì)象 subType.prototype = prototype;//指定對(duì)象 } function SuperType(name){ this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name,age){ SuperType.call(this,name); this.age = age; } inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function(){ alert(this.age); }
以上就是本文的全部?jī)?nèi)容,javascript實(shí)現(xiàn)繼承的方式,感謝大家的閱讀,小編會(huì)再接再厲!
- JS 面向?qū)ο笾^承---多種組合繼承詳解
- JS面向?qū)ο螅?)之Object類,靜態(tài)屬性,閉包,私有屬性, call和apply的使用,繼承的三種實(shí)現(xiàn)方法
- 詳解JavaScript基于面向?qū)ο笾^承實(shí)例
- 詳解JavaScript基于面向?qū)ο笾^承
- Javascript簡(jiǎn)單實(shí)現(xiàn)面向?qū)ο缶幊汤^承實(shí)例代碼
- javascript 面向?qū)ο蠓庋b與繼承
- javaScript面向?qū)ο罄^承方法經(jīng)典實(shí)現(xiàn)
- JS Pro-深入面向?qū)ο蟮某绦蛟O(shè)計(jì)之繼承的詳解
- 關(guān)于JavaScript的面向?qū)ο蠛屠^承有利新手學(xué)習(xí)
- 徹底理解js面向?qū)ο笾^承
相關(guān)文章
一個(gè)獲取第n個(gè)元素節(jié)點(diǎn)的js函數(shù)
這篇文章主要介紹了一個(gè)獲取第n個(gè)元素節(jié)點(diǎn)的js函數(shù),功能還不完善 ,需要的朋友可以參考下2014-09-09js實(shí)現(xiàn)簡(jiǎn)單的前端分頁效果
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)簡(jiǎn)單的前端分頁效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08JavaScript與Div對(duì)層定位和移動(dòng)獲得坐標(biāo)的實(shí)現(xiàn)代碼
JavaScript與Div對(duì)層定位和移動(dòng)獲得坐標(biāo)的實(shí)現(xiàn)代碼,需要的朋友可以參考下。2010-09-09JavaScript中forEach和map詳細(xì)講解
foreach和map都是JavaScript中數(shù)組的常用方法,它們都可以對(duì)數(shù)組中的每個(gè)元素執(zhí)行一個(gè)函數(shù),但是它們有一些區(qū)別,下面這篇文章主要給大家介紹了關(guān)于JavaScript中forEach和map詳細(xì)講解的相關(guān)資料,需要的朋友可以參考下2023-11-11JavaScript股票的動(dòng)態(tài)買賣規(guī)劃實(shí)例分析下篇
這篇文章主要介紹了JavaScript對(duì)于動(dòng)態(tài)規(guī)劃解決股票問題的真題例舉講解。文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08