摘要:第二個問題是在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。實際上,應該說是沒有辦法在不影響所有對象實例的情況下,給炒類型的構造函數傳遞參數。借用構造函數偽造對象或經典繼承即在子類型構造函數的內部調用超類型構造函數。
繼承
許多 OO 語言支持兩種繼承方式:接口繼承和實現繼承。接口繼承只繼承方法簽名,而實現繼承則繼承實際的方法。如前所述,由于函數沒有簽名,在 ECMAScript 中無法實現接口繼承。 ECMAScript 只支持實現繼承,而且其實現繼承主要是依靠原型鏈來實現。
原型鏈基本思想是:利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。
構造函數、原型和實例的關系:每個構造函數都有一個原型對象,原型對象都包含一個指向構造函數的指針,而實例都包含一個指向原型對象的內部指針。
jsfunction SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty = false; } //繼承了 SuperType SubType.prototype = new SuperType(); SuperType.prototype.getSubValue = function() { return this.subproperty; } var instance = new SubType(); alert(instance.getSuperValue());//true
別忘記默認的原型
確定原型和實例的關系
jsalert(instance instanceof Object); //true alert(instance instanceof SuperType); //true alert(instance instanceof SubType); //true
jsalert(Object.prototype.isPrototypeOf(instance));//ture alert(SuperType.prototype.isPrototypeOf(instance));//ture alert(SubType.prototype.isPrototypeOf(instance));//ture
謹慎地定義方法
給原型添加方法的代碼一定要放在替換原型的語句之后。
jsfunction SuperType() { this.property = true; } SuperType.protype.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
jsfunction 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; }, someOtherMethod = function() { return false; } }; var instance = new SubType(); alert(instance.getSuperValue()); //error 原型鏈被切斷(現在的原型包含的是 Object 的實例)。
4.原型鏈的問題
最主要的問題來自包含引用類型值的原型。前面已經介紹過包含引用類型值的原型屬性會被所有實例共享,這也是為什么要在構造函數中而不在原型對象中定義屬性的原因。
第二個問題是:在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。實際上,應該說是沒有辦法在不影響所有對象實例的情況下,給炒類型的構造函數傳遞參數。
即在子類型構造函數的內部調用超類型構造函數。函數只不過是在特定環境中執行代碼的對象,所以可通過 apply() 或 call() 方法也可以在(將來)新創建的對象上執行構造函數。
jsfunction 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"
傳遞參數
js function SuperType(name) { this.name = name; } function SubType() { //繼承了 SuperType,同時還傳遞了參數 SuperType.call(this,"PaddingMe"); //實例屬性 this.age = 25; } var instance = new SubType(); alert(instance.name); //"PaddingMe" alert(instance.age); //25組合繼承(偽經典繼承)
即將原型鏈和借用構造函數的方法組合在一起,思路為使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承。
js function SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function() { alert(this.name); } function SubType() { //繼承屬性 SuperType.call(this,name); this.age = age; } SubType.prototype = new SuperType(); SubType.prototype.constuctor = SubType(); SubType.prototype.sayAge = function() { alert(this.age); } var instance1 = new("PaddingMe",25); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" instance1.sayName; //"PaddingMe" instance1.sayAge; //25 var instance2 = new("hw",26); alert(instance2.colors); //"red,blue,green" instance2.sayName; //"hw" instance2.sayAge; //26原型式繼承
js function object(o) { function F(){} F.prototype = o; return new F(); } var person = { name : "PaddingMe"; friends :["hw","wjj","hz"]; } var antherPerson = object(person); antherPerson.name = "Hhb"; antherPerson.friends.push("zxp"); var yetAntherPerson = object(person); yetAntherPerson.name = "Linda"; yetAntherPerson.friends.push("him"); alert(person.friends)//"hw,wjj,hz,zxp,him"
ECMAScirpt 5 中新增 Object.create() 方法規范化了原型式繼承。有兩個參數,一個用作新對象原型的對象和(可選的)一個為新對象定義額外屬性的對象。
在傳入一個參數情況下,Objetc.create() 和 object() 方法的行為相同。
js var person = { name : "PaddingMe"; friends :["hw","wjj","hz"]; } var antherPerson = Object.create(person); antherPerson.name = "Hhb"; antherPerson.friends.push("zxp"); var yetAntherPerson = Object.create(person); yetAntherPerson.name = "Linda"; yetAntherPerson.friends.push("him"); alert(person.friends)//"hw,wjj,hz,zxp,him"
第二個參數與 `Object.defineProperties() 方法的第二個參數格式相同: 每個屬性都是通過自己的描述符定義的。
js var person = { name : "PaddingMe"; friends :["hw","wjj","hz"]; } var anthorPerson = Object.create(person, { name: { value:"hehe"; } }) alert(anthorPerson.name);//"hehe"寄生式繼承
即創建一個僅用于封裝繼承構成的函數,該函數在內部以某種方式來增強對象,最后再像真地是它做了所有工作一樣返回對象。
js function createAnother(original) { var clone = object(original); //通過調用函數創建一個新對象 clone.sayHi = function() { //以某種方式來增強這個對象 alert("hi"); }; return clone; //返回這個對象 } var person = { name : "PaddingMe"; friends :["hw","wjj","hz"]; } var anthorPerson = createAnother(person); anthorPerson.sayHi();//"hi"寄生組合式繼承
jsfunction 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); //第二次調用SuperType(); this.age = age; } SubType.prototype = new SuperType(); // 第一次調用SuperType(); SubType.prototype.constuctor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); }
所謂寄生組合式繼承,即通過借用構造函數來繼承屬性,通過原型鏈的混成形式來繼承方法。基本思路為:不必為了指定子類型的原型而調用超類型的構造函數,我們所需要的無非是超類型原型的一個副本而已。本質上,就是使用寄生式繼承來繼承超類型的原型,然后再將結構指定給子類型的原型。寄生組合式繼承的基本模式:
js function inheritPrototype(subType,superType){ var prototype = object(superType.prototype); //創建對象 prototype.constructor = subType; //增強對象 subType.prototype = prototype; // 指定對象 }
jsfunction 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); //第二次調用SuperType(); this.age = age; } inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function(){ alert(this.age); }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85501.html
摘要:子類繼承自父類的方法可以重新定義即覆寫,被調用時會使用子類定義的方法什么是多態青蛙是一個對象,金魚也是一個對象,青蛙會跳,金魚會游,定義好對象及其方法后,我們能用青蛙對象調用跳這個方法,也能用金魚對象調用游這個方法。 1、專用術語 面向對象編程程序設計簡稱:OOP,在面向對象編程中常用到的概念有:對象、屬性、方法、類、封裝、聚合、重用與繼承、多態。 2、什么是對象? 面向對象編程的重點...
摘要:實際上,可以將其理解為某種形式的繼承。如果上下文是,則使用全局對象代替。例如的第個參數是上下文,后續是實際傳入的參數序列中允許更換上下文是為了共享狀態,尤其是在事件回調中。 公開記錄學習JS MVC,不知道能堅持多久= =。以《基于MVC的JavaScript web富應用開發》為主要學習資料。接上一篇類的學習,發現實在是看暈了,有些例子是能看懂在干嘛,但是不知道為什么這樣做,有的甚至...
摘要:繼承原型鏈如果構造函數或對象的原型指向構造函數或對象,的原型再指向構造函數或對象,以此類推,最終的構造函數或對象的原型指向的原型。 繼承 原型鏈 如果構造函數或對象A的原型指向構造函數或對象B,B的原型再指向構造函數或對象C,以此類推,最終的構造函數或對象的原型指向Object的原型。由此形成了一條鏈狀結構,被稱之為原型鏈。按照上述的描述,在B中定義的屬性或方法,可以在A中使用并不需要...
摘要:即另外,注意到構造函數里的屬性,都沒有經過進行初始化,而是直接使用進行綁定。并且在模式下,構造函數沒有使用進行調用,也會導致報錯。調用構造函數千萬不要忘記寫。 1. 基礎 JavaScript不區分類和實例的概念,而是通過原型來實現面向對象編程。Java是從高級的抽象上設計的類和實例,而JavaScript的設計理念,聽起來就好比Heros里的Peter,可以復制別人的能力。JavaS...
摘要:例例通過原型鏈來檢測對象所調用的方法是否存在,存在在哪個原型對象上除了在對象對象中存在外,其他方法都是通過原型鏈的方法在上找到并調用。 前言 學習了解JavaScript對象的繼承機制 JavaScript Object 概念 Object是js的基本數據結構的一種,屬于引用類型。 對象的創建方法 對象字面量寫法 構造函數,通過構造函數來創建對象實例 Object()構造函數 cre...
閱讀 749·2021-10-14 09:43
閱讀 2072·2021-09-30 09:48
閱讀 3440·2021-09-08 09:45
閱讀 1090·2021-09-02 15:41
閱讀 1878·2021-08-26 14:15
閱讀 770·2021-08-03 14:04
閱讀 2972·2019-08-30 15:56
閱讀 3072·2019-08-30 15:52