首页 > 试题广场 >

说一下类的创建和继承

创建一个类

/* 定义一个动物类 */
function Animal (name) {
  /* 属性 */
  this.name = name || 'Animal';
  /* 实例方法 */
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
 
/* 原型方法 */
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};


这样就生成了一个Animal类,实例化对象后,有方法和属性。

1. 原型链继承

function Cat(){ }
Cat.prototype = new Animal();  /* 原型继承 */
Cat.prototype.name = 'cat';
 
var cat = new Cat();

介绍:

    将超类的实例当作子类原型,形成一条原型链,访问子类上不存在的方法时,就可以通过这条原型链来寻找。

可以解决的问题:

  1. 方法公共化,不再需要被每个实例化对象携带

遗留的问题:

  1. 无法实现多继承
  2. 超类中引用类型变量被复用
  3. 无法向超类传参

2. 构造继承

function Cat(name){
  Animal.call(this);  /* 构造继承 */
  this.name = name || 'Tom';
}
var cat = new Cat();

介绍:

  在实例化子类对象的内部,以子类的名义(call)调用超类构造函数,来实现对超类的属性的继承。

可以解决的问题:

  1. 实现了多继承(每个继承的超类都在子类构造函数内部调用call即可)
  2. 可以向超类传参(call第二个参数即为向超类传递的参数)
  3. 超类中引用类型的变量被子类继承后属于某个实例化对象

遗留的问题:

  1. 直接将方法写在超类内部,会导致每个实例都有相同方法

3. 组合继承

function Cat(name){
  Animal.call(this);   /* 第二次调用 Animal */
  this.name = name || 'Tom';
}
Cat.prototype = new Animal();   /* 第一次调用 Animal */
Cat.prototype.constructor = Cat;
 
var cat = new Cat();

介绍:

  结合构造继承和原型继承,将二者的优势相结合。

可以解决的问题:

  1. 实现了多继承
  2. 可以向超类传参
  3. 超类中引用类型变量被子类继承后也可以私有化
  4. 方法公共化,不再需要被每个实例化对象携带

遗留的问题:

  1. 超类构造函数被调用了两次
  2. 超类中的属性被继承了两次(第一次调用Animal时,将超类构造函数Animal中的属性继承到子类构造函数Cat的原型中。new Cat()时,调用Animal.call()再次将超类构造Animal中的属性继承到子类构造Cat中

4. 寄生组合继承

// 圣杯继承(添加一个中间函数,由中间函数继承原型链)
function object(o){
  function F(){};
  F.prototype = o;
  return new F();
}

/* ------------- 寄生组合继承核心 ----------------- */
function inheritPrototype(subType, superType){
  let prototype = object(superType.protoType); /* 创建一个继承了“父类原型”的对象,将其作为子类的原型 */
  subType.prototype = prototype;
  prototype.constructor = subType;             /* 完善原型链 */
  
}
/* -------------------------------------------------- */

Animal.prototype.sayName = function(){
  console.log(this.name);
}

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}

inheritPrototype(Cat, Animal);  /* 寄生组合继承 */

var cat = new Cat();

该方法就是在组合继承的基础上,对组合继承遗留的问题进行优化。

可以解决的问题:
  1. 借助“圣杯继承”,在中间加入一个对象,起到了隔离的作用,后面为子类原型添加属性时,全部都会加在这个对象中,不会对父级产生影响。
  2. 避免使用组合继承中的原型继承,可以减少一次对父类的实例化,同时减少了原型中的脏属性
编辑于 2023-11-18 12:06:18 回复(0)
new 的function 是没有 prototype属性吧
发表于 2019-10-19 23:31:21 回复(2)