xvno / blog

个人博客, 不定期发布技术笔记和个人随笔.
0 stars 0 forks source link

前端: JavaScript: ES5 类继承方式 #33

Open xvno opened 5 years ago

xvno commented 5 years ago

[2019-4-27] 这些组合就是抬杠~ 就两种继承方式: 1. 原型链 2. class-extends

[2020-5-19] **这些组合就是抬杠~ 就一种继承方式: 原型继承

xvno commented 5 years ago

以下对"构造函数"使用别名"类", 如无特殊说明, 就用构造函数代表类.

纯原型链继承

B 继承 A

// 类: A
// 类: B
B.prototype = new A();

好处是简单有效, 坏处看这里 普通对象修改原型内属性时存在的tricks

xvno commented 5 years ago

构造函数盗用 (Constructor Stealing)

实现方式

考虑到 "new" 如此风骚(在neu内部调用Constructor.call({})), 可以在B内调用A.call(<B的this>), 即

function B() {
  A.call(this);
}

存在的问题

A仅仅作为一个函数使用, A上所有的其他属性/方法, B是绝对享受不到的. 这算继承?! 只算个半成品.

function A() {
  this.name = 'A';
}
A.prototype.getName = function() {
  return this.name;
};
A.prototype.version = '0.0.1';

function B() {
  A.call(this);
}

let b = new B();
console.log(b.name);
console.log(b.getName);  // undefined
console.log(b.version);   // undefined

改良

上面确定了一个半成品: 只有构造方法, 没有继承. 那么, 只需要把继承的东西挂上即可, 于是有了下面的组合继承.

xvno commented 5 years ago

组合实现 (Combination Inheritance)

function A () {
  this.name = 'A';
}

function B () {
  A.call(this);  // 构造函数偷用
}

B.prototype = new A();  // 原型链继承
B.prototype.constructor = B;  // [注1][1]
// B.prototype = Object.create(new A(), { constructor: {value: B}}); // 上面两句可用这一句替换
B.prototype.title = ['SE', 'CTO'];

说明

  1. 通过构造函数继承实例属性
  2. 用原型链继承方式继承共享的属性和方法

[1]: 什么时候重新赋值? 看情况! 如果考虑instanceof正确的话, 得这么做; 另外, .constructor是一个引用值, 它指向具体的构造函数, 如果要调用的话直接这样: B.prototype.constructor(). 参考这里

xvno commented 5 years ago

原型式继承

利用Object.create(原型对象)来创建继承对象. 下面实现aa继承自a

function A () {
  this.name = 'A';
}
let a = new A();

let aa = Object.create(a); // aa继承a

// aa.__proto__ === a -> true

说明

  1. 无构造函数
  2. 对原型对象进行浅复制
xvno commented 5 years ago

寄生式继承 (Parasitic)

考虑到给出的被继承目标a是个普通object, 用 Object.create(a) 返回一个继承了a的新对象.

function inheritFrom(origin) {
  let o = Object.create(origin);
  o.getName = function() {
    return this.name;
  }
  return o;
}

let b = inheritFrom(new A()); // 

说实话, 这种"继承"方式真无聊. 接下来还有更无聊的寄生组合式继承.

xvno commented 5 years ago

寄生组合式继承

function Super() { };
function Sub () {};

function inheriteCombination(Sub, Super) {
  let proto = Object.create(Super.prototype);
  proto.constructor = Sub;
  Sub.prototype = proto;
}