• 深入理解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上面绑定实例属性。

  • 相关阅读:
    javaScript表单焦点自动切换
    JavaScript禁止用户多次提交方法
    javaScript事件机制兼容【整理】
    DOM元素尺寸和位置(clientwidth ,scrollwidth , offsetwidth.......)
    javaScript给元素添加多个class
    javaScript增加样式规则(新增样式)
    javaScript动态添加样式
    工作中遇到的各种jar包说明
    springboot—Jpa原生sql使用
    Des3EncryptionUtil加密与解密
  • 原文地址:https://www.cnblogs.com/yangzhou33/p/13875917.html
Copyright © 2020-2023  润新知