前言
各位大佬們都來了就花點時間看看吧 看了之後來個小心心吧 不然沒有動力繼續寫下去呀 哈哈
開始
預備知識
原型鏈知識---話不多說先上圖,一圖勝千言
現在來寫一個基本的函式例項來解釋這幅圖function Test () {
this.name = 'test';
}
var fn = new Test;
console.log(fn.name);
//我們稱Test為建構函式 fn為建構函式Test的例項
//Test的prototype(原型)和例項的__proto__(原型)都指向了原型同一個原型物件
//原型物件的constructor指向了建構函式
複製程式碼
Object.create 再來一張圖片很清晰的解釋它的作用
下面開始玩轉繼承第一類 最簡單的繼承---原型繼承
// 原型繼承
function A() {
this.x = 'test';
}
A.prototype.getX = function () {
console.log(this.x);
};
function B() {
this.y = 'test2';
}
B.prototype = new A;
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test
複製程式碼
總結
這樣就實現了B的例項fn繼承了父類(A)中的所有屬性和方法。我們把A自己的屬性和方法(x)叫做私有屬性,父類(A)原型上的方法和屬性(getX)叫做公有屬性。這種繼承方式就是把父類(A)的公有屬性和私有屬性都繼承到了子類(B)的公有屬性中。
優點:簡單實用
缺點:因為只是改變了prototype的指向導致constructor都指向了A,且都變成了自己的公有屬性
改進方法
// 原型繼承
function A() {
this.x = 'test';
}
A.prototype.getX = function () {
console.log(this.x);
};
function B() {
this.y = 'test2';
}
B.prototype = new A;
B.prototype.constructor = B;//手動改變constructor
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test
複製程式碼
第二種 利用call改變this指向---call繼承
// call繼承
function A() {
this.x = 'test';
}
A.prototype.getX = function () {
console.log(this.x);
};
function B() {
this.y = 'test2';
A.call(this);
}
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
複製程式碼
總結
這樣就實現了B的例項fn繼承了A中的私有屬性和方法。這種繼承方式就是把A的私有有屬性繼承到了B的私有屬性中。
優點:簡單
缺點:只能繼承父類的私有屬性
第三種 複製屬性實現繼承---冒充物件繼承
//冒充物件繼承
function A() {
this.x = 'test';
}
A.prototype.getX = function () {
console.log(this.x);
};
function B() {
this.y = 'test2';
var temp = new A;
for (key in temp) {
// this=>例項fn
this[key] = temp[key];
}
temp = null;
}
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
複製程式碼
總結
這樣就實現了B的例項fn繼承了A中的私有屬性和方法。這種繼承方式就是把A的私有有屬性繼承到了B的私有屬性中。
缺點:只能繼承父類的私有屬性
第四種 混合模式繼承
//混合模式繼承
function A() {
this.x = 'test';
}
A.prototype.getX = function () {
console.log(this.x);
};
function B() {
this.y = 'test2';
A.call(this);
}
B.prototype = new A;
B.prototype.constructor = B;//手動改變constructor
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test
複製程式碼
總結
這樣就實現了B的例項fn繼承了A中的所有屬性和方法。這種繼承方式就是把父類(A)的公有屬性和私有屬性都繼承到了子類(B)的公有屬性中並且把父類的私有屬性繼承到了子類的私有屬性中。
優點:很全面
缺點:因為只是改變了prototype的指向導致constructor都指向了父類(A),複製了兩份父類的私有屬性
第五種 Create繼承模式
//Create模式繼承
function A() {
this.x = 'test';
}
A.prototype.getX = function () {
console.log(this.x);
};
function B() {
this.y = 'test2';
A.call(this);
}
B.prototype = Object.create(A.prototype);
B.prototype.constructor = B;//手動改變constructor
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test
複製程式碼
總結
這樣就實現了B的例項fn繼承了A中的所有屬性和方法。**這種繼承方式就是把父類(A)的公有屬性和私有屬性分別都對應繼承到了子類(B)的公有屬性和私有屬性中。
優點:很全面
缺點:Obiect.create 方法不支援IE 6 7 8
改進為相容版本
//Create模式繼承 相容
function A() {
this.x = 'test';
}
A.prototype.getX = function () {
console.log(this.x);
};
function B() {
this.y = 'test2';
A.call(this);
}
B.prototype = myCreate(A.prototype);
B.prototype.constructor = B;//手動改變constructor
var fn = new B;
console.log(fn.x);//=>test
console.log(fn.y);//=>test2
fn.getX();//=>test
function myCreate (o) {
function fn () {}
fn.prototype = o ;
return new fn;
}
複製程式碼
總結
每種方式都有優點和缺點,推薦想簡單使用第一種但最好使用最後一種。
寫文章不容易希望各位小哥哥、小姐姐、大佬們給個小心心吧。