JS | 构造函数的继承

2019-04-29  本文已影响0人  灬劣徒
//定义两个构造函数
function Animal() {
  this.species = '动物';
}

function  Cat(name.color) {
  this.name = name;
  this.color = color;
}

&&&

1.使用call和apply方法

这种方法是最简单的方法,使用call和apply方法,.把父对象的构造函数绑定在子对象上

Animal.apply(this,arguments) 或 Animal.call(this,name,color)

function Cat(name,color) {
  Animal.apply(this,arguments);
  this.name = name;
  this.color = color;
}
let cat = new Cat('大毛','黄色');
cat.species;  // '动物'

2.原型式继承

这种是最常见的,把一个构造函数的prototype,指向另一个构造函数的实例

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat; //这种方式丢失了原来的constructor属性,所以要手动纠正
let cat = new Cat('二毛','绿色');
cat.species;  // '动物'

//每一个实例也有constructor属性,默认调用prototype属性的constructor
cat.constructor = Cat.prototype.constructor;  // true

3.直接继承prototype

这种方法是对上一种方法的改进.在Animal对象中,共用的属性都可以写入Animal.prototype,所以我们也可以让Cat() 跳过Animal(),直接继承Animal.prototype

//先改写Animal的prototype属性
function Animal() {}
Animal.prototype.species = '动物';
Cat.prototype = Animal.prototype;
Cat.prototype.constructor = Cat;
let cat = new Cat('三毛','蓝色');
cat.species = '动物';

优点:与上一种方法相比,这样做的效率比较高(不用创建Animal的实例了),比较节省内存.
缺点:因为Cat.prototype和Animal.prototype都指向同一个对象,那么任何对Cat.prototype的修改,都会反应到Animal.prototype

4.利用空对象作为中介

直接继承prototype存在上述缺点,所以就有了第四种写法,利用一个空对象作为中介

function F(){}
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;

//这时,修改Cat.prototype对象就不会影响到Animal.prototype 
Animal.prototype.constructor; // Animal

把上面这种形式封装成一个方法,便于使用

function extend(Child,Parent) {
  let F = function() {};
  F.prototype = Parent.prototype;
  Child.protype = new F;
  Child.prototype.constructor = Child;
  Child.uber = Parent.prototype;
}

这个extend方法,就是YUI库如何实现继承的方法

另外,特别说明一点,函数体最后一行代码 Child.uber = Parent.prototype
意思是为子对象设置一个uber属性,这个属性直接指向父对象的prototype(uber德语的意思是'向上','上一层'),这等于在子对象上打开了一条通道,可以直接调用父对象上的方法.这一行放在这里,只是为了继承的完备性,纯属备用性质

5.拷贝继承

上面是利用了prototype对象实现了继承.我们也可以换一种思路,纯粹采用'拷贝'实现继承.简单说,就是把父对象上的所有属性和方法,都拷贝到子对象身上,这样不也能够实现继承吗

首先还是把Animal身上所有的共用方法,都放到prototype上

function Animal(){} 
Animal.prototype.species = '动物';

接下来是继承方法,实现属性拷贝

function extend(Child,Parent) {
  let p = Parent.prototype;
  let c = Child.prototype;
  for(let i in p) {
    c[i] = p[i];
  }
  c.uber = p.prototype;
}

这个对象的目的,就是把Parent.prototype上的属性,逐一拷贝给Child.prototype

原文摘自JS 面向对象编程(二)

上一篇下一篇

猜你喜欢

热点阅读