zoukankan      html  css  js  c++  java
  • 深入理解class和装饰器(上)

    深入理解class和装饰器

    class 的出现大大简化了 javascript 中类的写法,而装饰器又是 class 里面非常实用的功能,但是老实说,它们都是语法糖,并没有引入新的功能,那它们的原理是怎样的呢?本文来一一探究。通过本文,您可以学到:

    1. class 语法糖的原理是什么?
    2. super 的原理是什么?有什么注意事项?
    3. 装饰器的原理是什么?
    4. vue-class-component 是怎么实现 vue 的 class 写法的?
    5. vue-property-decorator 是怎么实现 watch 装饰器的?

    class 语法糖

    我们首先用 class 的写法写一个 demo:

    class A {
      constructor(name) {
        this.name = name;
      }
    
      say() {
        console.log(this.name);
      }
    
      static move() {
        console.log('move');
      }
    }
    
    class B extends A {
      constructor() {
        this.a = 1;
        super();
        this.b = 2;
      }
    
      hello() {
        console.log('hello');
      }
    
      static go() {
        console.log('go');
      }
    }
    

    通过分析 babel 打包后的代码,其实可以简化成下面这样:

    var A = /*#__PURE__*/function () {
      function A(name) {
        this.name = name
      }
    
      A.prototype.say = function say() {
        console.log(this.name)
      }
    
      A.move = function move() {
        console.log('move')
      }
    
      return A
    }()
    
    var B = /*#__PURE__*/function (_A) {
      var _super = function _createSuperInternal() {
        return _A.apply(this, arguments) || this
      }
    
      function B() {
        var _this;
    
        // _this.a = 1; // 这里会出现 _this 未定义,导致报错,所以不能在 super 之前绑定实例属性
        _this = _super.call(this)
        console.log(_this)
        _this.b = 2;
        return _this;
      }
    
      // 这里其实等价于:
      // B.prototype = Object.create(_A.prototype)
      // B.prototype.constructor = B
      B.prototype = Object.create(_A.prototype, {
        constructor: {
          value: B,
          writable: true,
          configurable: true
        }
      })
    
      B.prototype.hello = function hello() {
        console.log('hello');
      }
    
      B.go = function go() {
        console.log('go');
      }
    
      return B;
    }(A);
    

    可以看到:

    1. class 语法糖原理其实就是使用 constructor 作为构造函数,然后在构造函数的 prototype 上面绑定实例方法,并且直接在构造函数上面绑定静态方法
    2. class 的继承就是组合继承的形式。

    关于 super

    我们从上面可以看到,super 其实是内部创建的一个方法,它使用构造函数继承的方法来继承实例属性。但由于 _this 其实是由 super 返回的,所以如果在 super 之前绑定实例属性的话,_this 还未定义,导致报错。所以在 super 之前不能绑定实例属性

    那这里的 _this 为什么不直接用自己的 this 呢?

    我们来思考这样一种场景,就是构造函数里面有返回值

    class C {
      constructor() {
        return {a:2}
      }
    }
    

    上面的类会被编译成:

    var C = /*#__PURE__*/function () {
      function C(name) {
        return {a:2}
      }
    
      return C
    }()
    

    我们在实例化这个类的时候,其实得到的是构造函数的返回值,即{a:2}这个对象。所以如果父类是这种返回对象的形式的话,子类在继承的时候,就必须在这个返回值上面绑定实例属性,而不是在自己的this上面绑定实例属性。

  • 相关阅读:
    LeetCode Power of Three
    LeetCode Nim Game
    LeetCode,ugly number
    LeetCode Binary Tree Paths
    LeetCode Word Pattern
    LeetCode Bulls and Cows
    LeeCode Odd Even Linked List
    LeetCode twoSum
    549. Binary Tree Longest Consecutive Sequence II
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/yangzhou33/p/13875917.html
Copyright © 2011-2022 走看看