L - JavaScript继承

类式继承(原型链继承)

实现

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,实现继承app

缺点:

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.若是父类的实例须要传入一些参数,那么两个子类实例初始化时某一属性值相同this

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指向了Aprototype

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了,即解决了类式继承的第一个、第二个问题以及第三个问题code

缺点

很明显,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上建立没必要要、多余的属性原型

相关文章
相关标签/搜索