Rashomon511 / MyBlog

用于记录学习过程中的笔记,以及自己产出的文章心得,便于梳理前端知识架构以形成自己的前端知识体系

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

es6类的继承和对象关联

Rashomon511 opened this issue · comments

es6实现的继承代码:

class Parent{
    constructor(name){
        this.name = name;
    }
    static sayHello(){
        console.log('hello');
    }
    sayName(){
        console.log('my name is ' + this.name);
        return this.name;
    }
}
class Child extends Parent{
    constructor(name, age){
        super(name);
        this.age = age;
    }
    sayAge(){
        console.log('my age is ' + this.age);
        return this.age;
    }
}
let parent = new Parent('Parent');
let child = new Child('Child', 18);

代码里有两条原型链

// 1、构造器原型链
Child.__proto__ === Parent; // true
Parent.__proto__ === Function.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true
// 2、实例原型链
child.__proto__ === Child.prototype; // true
Child.prototype.__proto__ === Parent.prototype; // true
Parent.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true

ES6 extends 继承,主要就是

    1. 把子类构造函数(Child)的原型(proto)指向了父类构造函数(Parent)
    1. 把子类实例child的原型对象(Child.prototype) 的原型(proto)指向了父类parent的原型对象(Parent.prototype)。
    1. 子类构造函数Child继承了父类构造函数Preant的里的属性。使用super调用的(ES5则用call或者apply调用传参)。
      2和3小点,可以通过寄生组合式继承实现。设是__proto__可以通过newObject.create和`Object.setPrototypeOf来实现,那么我们可以来实现es5的继承
// ES5 实现ES6 extends的例子
function Parent(name){
    this.name = name;
}
Parent.sayHello = function(){
    console.log('hello');
}
Parent.prototype.sayName = function(){
    console.log('my name is ' + this.name);
    return this.name;
}

function Child(name, age){
    // 相当于super
    Parent.call(this, name);
    this.age = age;
}
// new
function object(){
    function F() {}
    F.prototype = proto;
    return new F();
}
function _inherits(Child, Parent){
    // Object.create
    Child.prototype = Object.create(Parent.prototype);
    // __proto__
    // Child.prototype.__proto__ = Parent.prototype;
    Child.prototype.constructor = Child;
    // ES6
    // Object.setPrototypeOf(Child, Parent);
    // __proto__
    Child.__proto__ = Parent;
}
_inherits(Child,  Parent);
Child.prototype.sayAge = function(){
    console.log('my age is ' + this.age);
    return this.age;
}
var parent = new Parent('Parent');
var child = new Child('Child', 18);

上述两中实现继承的方式都是通过 [[Prototype]] 机制来实现的,我们可以使用对象关联的风格来实现上述功能

  Parent = {
    init: function(value){
      this.name = value
    },
    sayHello: function(){
      console.log('hello');
    },
    sayName: function(){
      console.log('my name is ' + this.name);
      return this.name;
    }
  }
  Child = Object.create( Parent );
  Child.sayAge = function(){
    console.log('my age is ' + this.age);
    return this.age;
  }
  var child1 = Object.create( Child );
  child1.init( "tom" );
  var child2 = Object.create( Child );
  child2.init('lili');
  child1.sayHello();
  child2.sayName();

从上面代码可以看出对象关联风格的代码显然更加简洁,因为这种代码只关注一件事:对象之间的关联关系,
使用类构造函数的话,你需要在同一个步骤中实现构造和初始化。然而,在许多情况下把这两步分开(就像对象关联代码一样)更灵活。
对象关联除了能让代码看起来更简洁(并且更具扩展性)外还可以通过行为委托模式简化代码结构