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);