ES6Class

1. 用法

class Animal{
  type='哺乳类';//声明到实例上

  constructor(){}//相当于function Animal(){}

  say(){}//放到原型上
  
  get a(){}//放到原型上 相当于Object.defineProperty(Animal.prototype,a,{get(){ }})

  static flag='动物'//静态属性 ES7 ES6只有静态方法
  
  static get flag(){return '动物'}//ES6静态属性 相当于Object.defineProperty(Animal,a,{get(){ }})
}

2. ES5类的继承

//Object.setPrototypeOf( Child.prototype , Father.prototype );
Child.prototype = Object.create( Animal.prototype ,{ constructor : { value : Child } } );
//create原理
 let create = (parentProto, constructor) => {
   function fn() { };
   fn.prototype = parentProto;
   let newFn = new fn;
   newFn.constructor = constructor;
   return newFn;
 }

3. ES6类的继承

call + Object.create() + Object.setPrototypeOf()

class Animal {
      constructor(name) {
        this.name = name;
      }
      static type() {
        console.log('动物');
      }
      say() {
        console.log('say');
      }
    }
    class Tiger extends Animal {
      constructor(name) {
        super(name)//这里super===Animal
      }
      static type() {
        super.type()//这里super===Animal
      }
      say() {
        super.say()//这里super===Animal.prototype
      }
    }

4. new的原理

function mockNew(constructor, ...args) {
      let obj = Object.create(null);
      Object.setPrototypeOf(obj, constructor.prototype)
      let value = constructor.call(obj, args);
      return value != null && typeof value === 'object' ? value : obj;
    }

5. 装饰器

在执行类之前可以进行包装,装饰器必须是一个函数,只能修饰类的属性和类的方法。参数分别是类的原型、装饰的key、和key对应的属性描述器。

    //装饰器 必须是一个函数,只能修饰类  (类中的属性 还有类中的方法) 参数分别是 类的原型 装饰的key 和key对应的属性描述器
    @type1('哺乳1')
    @type2('哺乳2')
    class Circle{
        @readonly PI = 3.14;
        @before
        say(){
            console.log('say')
        }
    }
    // 对类进行扩展
    function type1(type1){
        console.log('t1')
        return function(Constructor){
            console.log('innerT1')
            Constructor.type1 = type1
        }
    }
    // 对类进行扩展
    function type2(type2){
        console.log('t2')
        return function(Constructor){
            console.log('innerT2')
            Constructor.type2 = type2
        }
    }
    //修饰属性
    function readonly(CirclePrototype,key,descriptor){
        descriptor.writable = false;
        descriptor.enumerable = false;
    }
    //修饰方法
    function before(CirclePrototype,key,descriptor){
        let oldSay = descriptor.value; // 函数劫持
        descriptor.value = function(){ // 将函数原有的逻辑 进行包装
            console.log('before')
            oldSay()
        }
    }
    let c = new Circle();
    c.say();
    // 实验型语法 目前node不支持
    // mixin 混合
    
    let obj = {
        name:'zf',
        age:'10',
    }
    @mixin(obj)
    class School{
    
    }
    function mixin(obj){
      return function(Constructor){
        Object.assign(Constructor.prototype,obj)
      }
    }
    let school = new School;
    console.log(school.name,school.age);