类式继承(原型链继承)

实现

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上创建不必要、多余的属性


None_
11 声望0 粉丝

会成为盖世英雄,没有七彩祥云


下一篇 »
L - 居中布局