类式继承(原型链继承)
实现
function A(){
this.a='a';
this.arr=[1,2];
}
A.prototype.funA=function(){
console.log("我是A的方法");
}
function B(){
this.b='b';
}
B.prototype.funB=function(){
console.log("我是B的方法");
}
B.prototype=new A();
var b1=new B();
由于A的实例能够访问A.prototype
,所以我们可以设置B.prototype
指向A的实例。所以B的实例可以访问A的实例以及A.prototype
,实现继承
缺点:
1.由于对象类型的赋值是引用赋值,如果父类A实例化过程中有引用类型,那么子类B的实例的这个属性都指向同一内存空间。
function A(){
this.a='a';
this.arr=[1,2];
}
A.prototype.funA=function(){
console.log("我是A的方法");
}
function B(){
this.b='b';
}
B.prototype.funB=function(){
console.log("我是B的方法");
}
B.prototype=new A();
var b1=new B();
var b2=new B();
b1.arr.push(3);
console.log(b1.arr); // [1, 2, 3]
console.log(b2.arr); // [1, 2, 3]
2.如果父类的实例需要传入一些参数,那么两个子类实例初始化时某一属性值相同
function A(year){
this.year=year;
}
function B(){
this.b='b';
}
B.prototype=new A(18);
var b1=new B();
var b2=new B();
console.log(b1.color); // 18
console.log(b2.color); // 18
3.B.prototype
中constructor指向不正确,因为B.prototype
指向了一个A的实例,所以本应指向B的constructor指向了A
function A(year){
this.year=year;
}
function B(){
this.b='b';
}
B.prototype=new A(18);
var b1=new B();
b1.constructor===A // true
构造函数继承(借用构造函数继承)
实现
function A(color){
this.a='a';
this.arr=[1,2];
this.color=color;
}
A.prototype.funA=function(){
console.log("我是A的方法");
}
function B(color){
A.call(this,color);
}
B.prototype.funB=function(){
console.log("我是B的方法");
}
var b1=new B("red");
console.log(b1) // {a: "a", arr: Array(2), color: "red"}
优点
解决了引用赋值问题,也可以自定义一些属性了,constructor也指向B了,即解决了类式继承的第一个、第二个问题以及第三个问题
缺点
很明显,B除了调用了A这个函数外并没有和A扯上什么关系,原型链是不通的(无法访问到应该作为父类的A的prototype属性),我甚至并不觉得这是一种继承方式,但它为下面两种方法奠定了基础
b1.__proto__===B.prototype // true
b1.__proto__.__proto__===Object.prototype // true
组合继承
说白了,就是将上述两种方法的长处组合到一起,利用原型链实现原型属性和方法的继承,通过借用构造函数实现对实例属性的继承
实现
function A(color){
this.a='a';
this.arr=[1,2];
this.color=color;
}
A.prototype.funA=function(){
console.log("我是A的方法");
}
function B(color,age){
// 通过借用构造函数实现对实例属性的继承
A.apply(this,[color]);
this.age=age;
}
// 利用原型链实现原型属性和方法的继承
B.prototype=new A();
B.prototype.constructor=B;
var b1=new B('red',18);
优点
既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性
缺点
调用了两次父类的构造函数
寄生组合式继承(此方法最好)
实现
function A(color){
this.a='a';
this.arr=[1,2];
this.color=color;
}
A.prototype.funA=function(){
console.log("我是A的方法");
}
function B(color,age){
A.apply(this,[color]);
this.age=age;
}
B.prototype=Object.create(A.prototype);
B.prototype.constructor=B;
var b1=new B('red',18);
优点
只需访问一次父类的构造函数,避免了在子类的prototype上创建不必要、多余的属性
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。