摘要:如繼承了這里就不必寫該方法的主要優勢就是可以在子類型構造函數中向超類型構造函數傳遞參數。以上原型式繼承通常只是想讓一個對象與另一個對象保持類似的情況下,原型式繼承是完全可以勝任的。
繼承
繼承分為接口繼承和實現繼承;接口繼承只繼承方法簽名,實現繼承則繼承實際的方法;由于函數沒有簽名,所以ECMAScript 中沒有接口繼承,只能依靠原型鏈來實現實現繼承。
原型鏈基本思想是利用原型鏈讓一個引用類型繼承另一個引用類型的屬性和方法:
如:Person2.prototype 是Person1.prototype 的繼承,那么(“--->” 意為“指向”):
Person2.prototype - [[Prototype]] ---> Person1.prototype Person2 - prototype ---> Person2 person2 - [[Prototype]] ---> Person2.prototype //Person2.prototype 無 constructor Person1.prototype - cunstructor ---> Person1 Person1 - prototype ---> Person1.prototype person1 - [[Prototype]] ---> Person1.prototype具體方法
具體如何繼承呢:
function People(){}; //原始的 People.prototype.sayWorld = function(){ return "World people" }; function Person(){}; //繼承的 Person.prototype = new People(); //這里應該注意要先繼承 Person.prototype.sayNation = function(){ //然后再修改prototype return "Chinese people" }; var person = new Person(); //實例 console.log(person.sayNation()); //Chinese people console.log(person.sayWorld()); //World people
一定要注意!!!給原型添加方法的代碼一定要放在替換原型的語句之后!!!
再舉個例子:
function WorldPeople(){}; WorldPeople.prototype = { constructor: WorldPeople, color: "", say: function(){ return "People in the Earth." }, friends: ["Oliver","Alice","Troy"] }; function Chinese(){}; Chinese.prototype = new WorldPeople(); Chinese.prototype.color = "yellow"; Chinese.prototype.say = function(){ return "i am Chinese." }; var person1 = new Chinese(); console.log(person1.friends.toString()); console.log(person1.color); console.log(person1.say()); /* [Log] Oliver,Alice,Troy (repetition.html, line 163) [Log] yellow (repetition.html, line 164) [Log] i am Chinese. (repetition.html, line 165) */確定原型和實例的關系
用instanceof 操作符和insPrototypeOf() 方法即可,如:
console.log(person1 instanceof Object); //true; console.log(person1 instanceof WorldPeople); //true; console.log(person1 instanceof Chinese); //true; console.log(Object.prototype.isPrototypeOf(person1)); //true console.log(WorldPeople.prototype.isPrototypeOf(person1)); //true console.log(Chinese.prototype.isPrototypeOf(person1)); //true謹慎定義方法
一定要記得,給原型添加方法的代碼一定要放在替換原型的語句之后!
還要記得,通過原型鏈實現繼承時,不能使用字面兩創建原型方法,因為這樣會重寫原型鏈!
原型鏈的問題包含引用類型值的原型,該屬性會被所有實例共享;
在創建子類型的實例時,不能向超類型的構造函數中傳遞參數;
對于第一種問題:
function People(){} People.prototype.friends = ["Alice","Oliver"]; function Person(){}; Person.prototype = new People(); var person1 = new Person(); var person2 = new People(); person1.friends.push("Troy"); console.log(person1.friends); console.log(person2.friends); //兩者完全相同
有什么解決辦法呢:
借用構造函數(不推薦使用)被稱為“借用構造函數”的技術或偽造對象或經典繼承。如:
function People(){ this.friends = ["Alice","Oliver"]; } function Person(){ People.call(this); //繼承了People } //這里就不必寫Person.prototype = new People() var person1 = new Person(); var person2 = new Person(); person1.friends.push("Troy"); console.log(person1.friends); //["Alice", "Oliver", "Troy"] console.log(person2.friends); //["Alice", "Oliver"]
該方法的主要優勢就是可以在子類型構造函數中向超類型構造函數傳遞參數。
又如:
function SuperType(name){ this.name = name; } function SubType(){ SuperType.call(this,"Oliver"); //這里不僅僅繼承了SuperType,而且還向它傳遞了參數 this.age = 18; } var person = new SubType(); console.log(person.name); //Oliver console.log(person.age); //18
由于函數不可復用等問題,不推薦使用。
組合繼承(最常用的模式)也叫做偽經典繼承。如:
//不通用的屬性 function SuperType(name){ this.name = name; this.colors = ["Blue","Red","Black"]; } //通用的方法 SuperType.prototype.sayName = function(){ return (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(){//新增方法 return (this.age); }; var person1 = new SubType("Oliver",18); var person2 = new SubType("Troy",24); person1.colors.pop(); console.log(person1.colors); console.log(person2.colors); console.log(person1.sayName() + person1.sayAge()); console.log(person2.sayName() + person2.sayAge()); /* [Log] ["Blue", "Red"] (repetition.html, line 255) [Log] ["Blue", "Red", "Black"] (repetition.html, line 256) [Log] Oliver18 (repetition.html, line 257) [Log] Troy24 (repetition.html, line 258) */
最常用的方法。再舉個例子:
function People(name,age){ this.name = name; this.age = age; this.friends = []; } People.prototype.friendsList = function(){ document.write(this.friends.toString()); }; function Person(name,age,color,job){ People.call(this,name,age); this.color = color; this.job = job; } Person.prototype = new People(); Person.prototype.constructor = Person; Person.prototype.sayInfo = function(){ document.write(this.name + this.age + this.color + this.job); }; var person1 = new Person("Oliver",18,"yellow","Hero"); person1.friends.push("Alice"); person1.sayInfo(); //Oliver18yellowHero person1.friendsList(); //Alice var person2 = new Person("Troy",24,"White","Fighter"); person2.friends.push("Oliver","Islan"); person2.sayInfo(); //Troy24WhiteFighter person2.friendsList(); //Oliver,Islan
平時用這個方法已經足夠。又如:
function Cars(name){ this.name = name; this.hasColor = ["blue","black"]; } Cars.prototype.sayName = function(){ console.log(this.name); }; function Car(name,color){ Cars.call(this,name); this.color = color; } Car.prototype = new Cars(); Car.prototype.constructor = Car; Car.prototype.sayColor = function(){ console.log(this.color); }; var benz = new Car("Benz-C200","Black"); benz.hasColor.push("red"); benz.sayName(); benz.sayColor(); console.log(benz.hasColor); var benz2 = new Car("Benz-C180","White"); benz2.hasColor.push("white"); benz2.sayName(); benz2.sayColor(); console.log(benz2.hasColor); /* [Log] Benz-C200 (repetition.html, line 309) [Log] Black (repetition.html, line 319) [Log] ["blue", "black", "red"] (repetition.html, line 325) [Log] Benz-C180 (repetition.html, line 309) [Log] White (repetition.html, line 319) [Log] ["blue", "black", "white"] (repetition.html, line 330) */
結合創建對象和繼承對象,來一個比較吧:
重要!
重要!
重要!
//組合使用構造函數模式和原型模式-創建對象 function Person(name,age){ this.name = name; this.age = age; this.friendsList = ["Alice","Islan"]; } Person.prototype.friends = function(){ console.log(this.friendsList.toString()); }; var person1 = new Person("Oliver",18); var person2 = new Person("Troy",24); person1.friendsList.pop(); person1.friends(); //Alice person2.friends(); //Alice,Islan
//組合繼承-繼承對象 function Person(name,age){ this.name = name; this.age = age; this.friendsList = ["Alice","Islan"]; } Person.prototype.friends = function(){ console.log(this.friendsList.toString()); }; function Info(name,age,job){ Person.call(this,name,age); this.job = job; } Info.prototype = new Person(); Info.prototype.constructor = Info; Info.prototype.sayJob = function(){ console.log(this.job); }; var person1 = new Info("Oliver",18,"Master"); var person2 = new Info("Troy",24,"Hero"); person1.friendsList.pop(); person1.friends(); //Alice person2.friends(); //Alice,Islan person1.sayJob(); //Master person2.sayJob(); //Hero
對比一下,就可以看出,繼承屬性主要應用到call 操作符給超類型構造函數傳遞參數;而繼承方法則要注意不可使用字面量語法。
以上
原型式繼承通常只是想讓一個對象與另一個對象保持類似的情況下,原型式繼承是完全可以勝任的。共享相應的引用類型的值的屬性。
語法是:
function object(o){ function F(){}; F.prototype = o; return new F(); }
如:
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Oliver", friends: ["Alice","Islan"] }; var anotherPerson = object(person); anotherPerson.name = "Troy"; anotherPerson.friends.push("Ellen"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Ellen"; yetAnotherPerson.friends.push("Troy","Oliver"); console.log(person.friends);
又如:
function object(o){ function F(){}; F.prototype = o; return new F(); } var person = { name: "Oliver", friends: ["Alice","Islan"] }; var anotherPerson = object(person); anotherPerson.name = "Troy"; anotherPerson.friends.push("Oliver"); console.log(person.friends);["Alice", "Islan", "Oliver"]
這種方法比較簡單,只是想讓person 和anotherPerson 保持類似并共享引用類型的值的屬性。
寄生式繼承(不能做到函數復用而導致效率降低)創建一個封裝繼承過程的函數而已:
function createAnotherObj(obj){ var clone = obj; clone.sayHi = function(){ console.log("hi"); }; return clone; } var person = { name: "Troy", friends: ["Alice"] }; var anotherObj = createAnotherObj(person); anotherObj.sayHi(); anotherObj.name = "Oliver"; anotherObj.friends.push("Ellen"); console.log(person.friends); console.log(anotherObj.friends); //兩個完全一樣寄生組合式繼承(最理想的繼承范式)
基本邏輯就是首先創建一個超類型原型的一個副本;然后為副本添加constructor 屬性;最后把副本賦值給子類型的原型。如:
function inheritPrototype(SubType,SuperType){ var prototype = Object(SuperType.prototype); prototype.constructor = SubType; SubType.prototype = prototype; } function SuperType(name){ this.name = name; this.color = ["red","yellow"]; } SuperType.prototype.list = function(){ console.log(this.color.toString()); }; function SubType(name,age){ SuperType.call(this,name); this.age = age; } inheritPrototype(SubType,SuperType); SubType.prototype.sayName = function(){ console.log(this.name); }; var type1 = new SubType("Oliver",18); var type2 = new SubType("Troy",24) type2.color.pop(); type1.list(); //red,yellow type2.list(); //red
應該常用這種模式,比較完善。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/86266.html
摘要:構造函數的兩個特征函數內部使用了,指向所要生成的對象實例。將一個空對象的指向構造函數的屬性,這個對象就是要返回的實例對象。用面向對象開發時,把要生成的實例對象的特有屬性放到構造函數內,把共有的方法放到構造函數的里面。 JS中面向對象的概念 面向對象OOP是一種組織代碼結構、實現功能過程的思維方式。它將真實世界各種復雜的關系,抽象為一個個對象,然后由對象之間的分工與合作,完成對真實世界的...
摘要:描述符對象就是上面提到的個描述其行為的特性和。真是奇怪讀取屬性的特征使用的方法,可以取得給定屬性的描述符。接收兩個參數所在的對象和要讀取其描述符的屬性名稱。 對象的基本概念 面向對象(Object-Oriented,OO),的語言最大的特征就是它們都有類的概念,通過類可以創建任意多個具有相同屬性和方法的對象。 創建自定義對象最簡單的方式就是創建一個Object 的實例,然后再給他添加屬...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
閱讀 3398·2023-04-25 22:04
閱讀 2197·2021-11-22 15:29
閱讀 2161·2021-10-11 10:57
閱讀 1402·2021-09-24 09:48
閱讀 3147·2021-09-09 09:34
閱讀 2543·2021-09-02 15:21
閱讀 2393·2019-08-30 15:53
閱讀 1120·2019-08-30 14:07