javascript高级程序设计的几种经典继承

文章目录

    • 构造方法继承
    • 原型链继承
    • 组合继承
    • 原型式继承
    • 寄生式继承
    • 寄生组合式继承

借鉴:https://www.jianshu.com/p/85899e287694

构造方法继承

优点:

  • 可以传参给父类利用call的参数列表传递
  • 避免了所有属性被实例共享

缺点:

  • 没创建一个实例 就要创造一个方法
  • 只能继承父类的实例属性和方法,不能继承原型的属性和方法

function Parent(name){
     
  this.name = name||'default_name';

  this.getInfo =function(){
     
    return this.name
  }
}

Parent.prototype.say = function(){
     
  console.log('hello');
}

function Child(name){
     
  Parent.call(this,name)
}

var child1 = new Child(['a']);
console.log(child1.name);// ["a"]
// child1.say(); //报错 只能继承父类的实例属性和方法,不能继承原型的属性和方法
// child1.name.push('Bob')
console.log(child1.getInfo()); // ["a"]

var child2 = new Child();
console.log(child2.getInfo());//["default_name"]

原型链继承

特点:所有实例共享属性和方法

function Parent(){
     
  this.name = ['sartre']
}

Parent.prototype.getName = function(){
     
  return this.name;
}

function Child(){
     

}

Child.prototype = new Parent()

var child1 = new Child();
console.log(child1.name); //["sartre"]

child1.name.push('mark') 
console.log(child1.name); // ["sartre", "mark"]

var child2 = new Child();
console.log(child2.name); // ["sartre", "mark"]

组合继承

融合前两者的有点,既可以共享原型方法而且不存在应用属性共享的问题,生成的实例既是子类的实例,优势父类的实例

function Parent(name){
     
  this.name = name;
  this.hobbies = ['guitar','run','ball'];
}

Parent.prototype.getName = function(){
     
  console.log(this.name);
}

function Child(name,age){
     
  Parent.call(this,name);
  this.age = age || 20;
}

// 弄懂原型和原型链的关系图 一下就能理解了
Child.prototype = new Parent();
child.prototype.constructor = Child;

var child1 = new Child('sartre','20');

child1.hobbies.push('swim')

console.log(child1.name);
console.log(child1.age);
console.log(child1.hobbies);

var child2 = new Child('mark');

console.log(child1.name);
console.log(child1.age);
console.log(child1.hobbies);

原型式继承

function createObj(o){
     
  function F(){
     

  }

  F.prototype = o;
  return new F();
}

// 就是 ES5 Object.create 的模拟实现 将传入的对象作为创建的对象的原型

// 缺点:
// 包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样

var person = {
     
  name:'kevin',
  friends:['daisy','kelly']
}

var person1 = createObj(person);
var person2 = createObj(person)

person1.name = 'person1';
console.log(person2.name); //kevin 这里不是引用类型所以 person2.name 没有改变

person1.friends.push('taylor');

console.log(person2.friends); // ["daisy", "kelly", "taylor"]

寄生式继承

这种方式的继承和构造函数继承的方式一样

function createObj(o){
     
  var clone = Object.create(o);
  clone.sayName = function(){
     
    console.log('hi');
  }
  return clone;
}

寄生组合式继承

这种继承方法是组合继承的进一步改进
前面的组合继承的缺点就是:会调用两次父构造函数

  • 第一次是设置子类型实例的原型的时候 Child.prototype = new Parent()
  • 第二次是在创建子类型实例的时候
  • var child1 = new Child(‘kevin’,18); 这里执行了new方法 那么就会
    执行 Parent.call(this,name) 调用了 Parent构造函数
function Parent (name) {
     
  this.name = name;
  this.colors = ['red', 'blue', 'green'];
}

Parent.prototype.getName = function () {
     
  console.log(this.name)
}

function Child (name, age) {
     
  Parent.call(this, name);
  this.age = age;
}


// 如果我们不使用 Child.prototype = new Parent() ,
// 而是间接的让 Child.prototype 访问到 Parent.prototype 呢?
var F = function(){
     

}
F.prototype = Parent.prototype

Child.prototype = new F();



你可能感兴趣的:(javascript高级程序设计的几种经典继承)