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