複製代碼 代碼如下:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.country = 'chinese';
Person.prototype.sayCountry = function() {
alert(this.country);
}
var zhangsan = new Person('zhangsan', 20);
var lisi = new Person('lisi', 20);
zhangsan.sayCountry(); //chinese
lisi.sayCountry(); //chinese
alert(zhangsan.sayCountry = //chinese
alert(zhangsan.sayCountry = //chinese
alert(zhangsan.sayCountry = = lisi.sayCountry); //true 複製程式碼
程式碼如下:
Person.prototype.friends = ['wang. ]; //Person新增一個陣列類型
zhangsan.friends.push('zhaoliu'); //張三修改會對李四造成影響
alert(zhangsan.friends); //wangwu,zhaoliu
alert(lisi.friends); //wangwu,zhaoliu李四也多了個
3、組合使用建構子模式和原型模式
這種模式是使用最廣泛、認同度最高的一種創造自訂類型的方式。建構函數模式用於定義實例屬性,而原型模式用於定義方法和共享的屬性。這樣,每個實例都有自己的一份實例屬性的副本,同時有共享著對方法的引用,最大限度的節省了記憶體。
原型模式改造後的如下:
複製程式碼
程式碼如下:
程式碼如下:
程式碼如下:
程式碼如下:
function Person(name, age) {
this.name = name;
this.age = age;
this.friends = ['wangwu'];
}
Person.prototype.country = 'chinese';
Person.prototype.sayCountry = function() {
alert(this.country);
}
var zhangsan = new Person(' zhangsan', 20);
var lisi = new Person('lisi', 20);
繼承基本概念
ECMAScript主要依靠原型鏈來依靠主要依靠原型鏈來主要依靠原型鏈來實現繼承(也可以透過拷貝屬性繼承)。
原型鏈基本思想是,利用原型讓一個引用型別繼承另外一個引用型別的屬性和方法。建構子、原型、範例的關係是:每個建構函式都有一個原型對象,原型對像都包含了一個指向建構函式的指針,而實例都包含了一個指向原型的內部指針。所以,透過過讓原型物件等於另外一個類型的實例,此時原型物件將包含一個指向另一個原型的指針,相應地,另一個原型中也包含這一個指向另一個建構函數的指針。假如另一個原型又是另一個類型的實例,那麼上述關係依然成立,如此層層遞進,就構成了實例和原型的鏈條。這就是原型鏈的基本概念。
讀起來比較繞,不容易理解。直接透過實例說明驗證。
1、原型鏈繼承
複製程式碼
程式碼如下:this.pname = 'parent';
}
Parent.prototype.getParentName = function() {
return this.pname;
} return this.pname; } function Child() { this.cname = 'child'; } //子建構函式原型設定為父建構子的實例,形成原型鏈,讓Child擁有getParentName方法Child .prototype = new Parent(); Child.prototype.getChildName = function() { return this.cname; } var c = new Child(); } var c = new Child(); } var c = new Child(); } var c = new Child(); } var c = new Child(); } var c = new Child(); alert(c.getParentName()); //parent
圖解:
原型鏈的問題,如果父類中包括了引用類型,透過Child.prototype = new Parent()會把父類別中的引用類型帶到子類別的原型中,而引用類型值的原型屬性會被所有實例共用。問題就回到了[一、2]節了。
2、組合繼承-最常用繼承方式
組合繼承(combination inheritance),是將原型鍊和借用構造函數(apply, call)的技術組合到一塊。想法是使用原型鏈實現對原型屬性和方法的繼承,而藉由借用建構函式來實現實例屬性的繼承。這樣既可以在原型上定義方法實現了函數的複用,又能保證每個實例都有它自己的屬性。
function Parent(name) {
function Parent(name) {
this <.name>this.colors = ['red', 'yellow'];
}
Parent.prototype.sayName = function() {
alert(this.name);
}
function Child(name, age) {
Parent.call(this, name); //第二次呼叫Parent()
this.age = age;
}
Child.prototype = new Parent(); //第一次呼叫Parent(),父類的屬性會
Child.prototype.sayAge = function() {
alert(this.age );
}
var c1 = new Child('zhangsan', 20);
var c2 = new Child('lisi', 21);
c1.colors.push( 'blue');
alert(c1.colors); //red,yellow,blue
c1.sayName(); //zhangsan
c1.sayAge(); //20
alert(c2.colors); //red,yellow
c2.sayName(); //lisi
c2.sayAge(); //21
組合繼承的問題是,每次都會呼叫兩次超類型建構函數:第一次是在創建子類型原型的時候,另一次是在子類型建構函數內部。這樣就會造成屬性的重寫 ,子類型建構函式中包含了父類別的屬性,而且子類別的原型物件中也包含了父類別的屬性。
3、寄生組合繼承-最完美繼承方式
所謂寄生組合繼承,即藉由借用構造函數來繼承屬性,透過原型鏈的混成形式來繼承方法。 背後的基本想法是:不必為了指定子類別的原型而呼叫超類型的建構函數,我們所需要的無非就是超類型原型的一個副本複製程式碼
程式碼如下:
function extend(child, parent) {
var F = function(){}; //定義一個空的建構子
F.prototype = parent.prototype; //設定為父類別的原型
child.prototype = new F(); //子類別的原型設定為F的實例,形成原型鏈
child .prototype.constructor = child; //重新指定子類別建構子指標
}
function Parent(name) {
this.name = name;
this.colors = [' red', 'yellow'];
}
Parent.prototype.sayName = function() {
alert(this.name);
}
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
extend(Child, Parent); //實作繼承
Child. prototype.sayAge = function() {
alert(this.age);
}
var c1 = new Child('zhangsan', 20);
var c2 = new Child( 'lisi', 21);
c1.colors.push('blue');
alert(c1.colors); //red,yellow,blue
c1.sayName(); //zhangsan
c1.sayAge(); //20
alert(c2.colors); //red,yellow
c2.sayName(); //lisi c2.sayAge() ; //21