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();



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值