ES5继承

作者: 悄敲 | 来源:发表于2019-03-04 14:07 被阅读0次

JS中没有其他面向对象中的“类”的概念,其继承方式主要通过“原型”,具体包括:单纯的原型链、借用构造函数(constructor stealing)、组合继承、原型式继承、寄生式继承、寄生组合式继承。其中寄生组合式继承被认为是引用类型最理想的继承范式。(上述几种继承范式的详细介绍,请查阅Nicholas C.Zakas所著Professional Javascript for Web Developers 3rd edition)
寄生组合式继承定义: 通过借用构造函数来继承属性,通过原型链来继承方法。此之所谓“组合”;由于指定“子类”的原型对象(prototype)时,所需的不过是“父类”原型的一个副本(浅拷贝即可),并不必调用“父类”的构造函数。本质上就是使用寄生式继承来继承“父类”的原型,再将结果指定给“子类”的原型。(这里为了便于描述使用了“父类”、“子类”,实际上称为superType、subType更准确)。
寄生组合式继承基本模式:

function inheritPrototype(SubType, SuperType) {
    let prototype=Object.create(SuperType.prototype); // 创建对象
    prototype.constructor=SubType; // 增强对象
    SubType.prototype=prototype; // 指定对象
}

代码块1
而在组合式继承中,则是通过代码块2所示,调用“父类”构造函数创建了一个实例,将此实例赋予“子类”的原型对象,这使得“子类”的原型对象中混入了“父类”实例属性,这往往并不是我们想要的。结果就需要在“子类”的构造函数SubType中,再次调用“父类”构造函数SuperType,来重写“子类”的原型对象中混入的“父类”实例属性。这种做法虽然可行,不过并不完美。

function inheritPrototype2(SubType, SuperType) {
    SubType.prototype=new  SuperType(); //第一次调用SuperType   
    SubType.prototype.constructor=SubType;                          
  }

代码块2

function SubType(可选初始化参数) {
    SuperType.call(this, 其他参数) ;   //第二次调用SuperType                      
  }

代码块3

寄生组合式继承优点: (1)只调用了一次SuperType构造函数,避免了在SubType.prototype上创建多余的属性;
(2)原型链保持不变,仍可正常使用instancesof 和 isPrototypeOf()来检测实例与特定引用数据类型、“父类”与“子类”继承关系。

下面两段代码分别说明继承单一类型和多个类型。

// Shape - 父类(superclass)
function Shape() {
  this.x = 0;
  this.y = 0;
}

// 父类的方法
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - 子类(subclass)
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?',
  rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
  rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'

代码块4 继承单一类型

function MyClass() {
     SuperClass.call(this);
     OtherSuperClass.call(this);
}

// 继承一个类
MyClass.prototype = Object.create(SuperClass.prototype);
// 混合其它
Object.assign(MyClass.prototype, OtherSuperClass.prototype);
// 重新指定constructor
MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {
     // do a thing
};

代码块5 继承多个类型

Note:

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的_proto_
Object.assign会把 OtherSuperClass原型上的函数拷贝到 MyClass原型上,使 MyClass 的所有实例都可用 OtherSuperClass 的方法。Object.assign 是在 ES2015 引入的,且可用 polyfilled。

ES6为了在继承上与传统面向对象语言更加类似,引入了class
ES5 的继承,实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this 上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到 this 上面(所以在 constructor 里必须先调用super方法),然后再用子类的构造函数修改this。

相关文章

网友评论

      本文标题:ES5继承

      本文链接:https://www.haomeiwen.com/subject/ukabuqtx.html