class(底层实现) 以及通过babel转换成es5代码解析

177 阅读4分钟

class extends

他的本质就是构造函数 原型链的语法糖 他分两种方式 类的声明 类的表达式 constructor 是class类的构造方法 在class声明的时候他就会被调用 如果没有这个构造方法的话 它会默认调用一个空的构造函数 一个类只会有一个构造函数 这个构造函数会默认执行5个步骤(跟new创建出来的构造函数比较相似)

  1. 在内存中生成一个空对象 mont={}
  2. 会将类的prototype赋予给创建的对象 mont.proto=Person.prototype
  3. 会讲对象赋值给函数的this。mont=this new绑定
  4. 执行函数体中的代码
  5. 返回这个对象

extends 继承 super : js引擎在解析子类的时候就有要求 如果我们实现继承extends 在使用this之前 或者return之前 必须调一下该的调用方法 super(name,age) 虽然语法逻辑在夫类中 但是在打印可以看出他还是在子类里

类的声明
Class Person  {
    constructor(name,age){
      this.name=name
      this.age=age
    }
    // 类的方法 都是定义在定义在原型上面的
    eating(){

    }
    // 类的访问器
    get name(){
        return this.name 
    }
    set name (name){
        this.name=name
    }
    // 类的静态方法 可以不通过new返回一个变量来使用 可以直接Person.creatPerson来使用
    static creatPerson(){
    var names = ["abc", "cba", "nba"]
    var nameIndex = Math.floor(Math.random() * names.length)
    var name = names[nameIndex]
    var age = Math.floor(Math.random() * 100)
    return new Person(name, age)
    }
}

// student交子类也可以叫为派生类
Class student extends Person{
      constructor(name,age){
       super(name,age)
    }
    eating(){
        // 可以用super复用父类的方法 可以先调用父类的方法 再接着自己逻辑
        super.eating()
        console.log('重写父类方法')
    }
    // 重写父类静态方法
    static creatPerson(){
     super.creatPerson()
     console.log('重写父类的静态方法')
    }
}

var pi = Person.creatPerson
类的表达式
var Animal=class{

}

es6-es5 Babel转换解析

class Person {
    constructor(name, age) {
      this.name = name
      this.age = age
    }
  
    eating() {
      console.log(this.name + " eating~")
    }
  }
  
  // babel转换
  "use strict";
  // 判断传入的类型   边界值判断
  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }
  
  function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
        // 获取到数组里面的内容
      var descriptor = props[i];
      // 设置描述属性
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      // 获取到value是否有值
      if ("value" in descriptor) descriptor.writable = true;
      // 通过Object.defineProperty添加到原型上
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }
  
  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    return Constructor;
  }
  
  //   这是是一个自执行函数 
  // /*#__PURE__*/ 纯函数 他的目的就是标记这段代码是纯函数 如果在打包编译期间 没有使用过的话 他就不会对这段代码进行编译
  // webpack 压缩 tree-shaking
  // 这个函数没副作用 所以即使不编译他也不会对其他代码进行影响
  

  var Person = /*#__PURE__*/ (function () {
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
  
    // Person.prototype.eating=function(){
   // 
    // }
    _createClass(Person, [
      {
        key: "eating",
        value: function eating() {
          console.log(this.name + " eating~");
        }
      }
    ]);
  
    return Person;
  })();

es6-es5 带继承源码解析

// class Person {
//   constructor(name, age) {
//     this.name = name
//     this.age = age
//   }

//   running() {
//     console.log(this.name + " running~")
//   }

//   static staticMethod() {

//   }
// }

// class Student extends Person {
//   constructor(name, age, sno) {
//     super(name, age)
//     this.sno = sno
//   }

//   studying() {
//     console.log(this.name + " studying~")
//   }
// }

// babel转换后的代码
"use strict";

function _typeof(obj) {
  "@babel/helpers - typeof";
  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
    _typeof = function _typeof(obj) {
      return typeof obj;
    };
  } else {
    _typeof = function _typeof(obj) {
      return obj &&
        typeof Symbol === "function" &&
        obj.constructor === Symbol &&
        obj !== Symbol.prototype
        ? "symbol"
        : typeof obj;
    };
  }
  return _typeof(obj);
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: { value: subClass, writable: true, configurable: true }
  });
  // 目的静态方法的继承
  // Student.__proto__ = Person
  if (superClass) _setPrototypeOf(subClass, superClass);
}

// o: Student
// p: Person
// 静态方法的继承 子类的proto等于父类的proto
function _setPrototypeOf(o, p) {
  _setPrototypeOf =
    Object.setPrototypeOf ||
    function _setPrototypeOf(o, p) {
      o.__proto__ = p;
      return o;
    };
  return _setPrototypeOf(o, p);
}

// super的函数转换 创建一个新的函数
function _createSuper(Derived) {
  var hasNativeReflectConstruct = _isNativeReflectConstruct();
  return function _createSuperInternal() {
    var Super = _getPrototypeOf(Derived),
      result;
      // Super: Person
// arguments: ["why", 18]
// NewTarget: Student
// 会通过Super创建出来一个实例, 但是这个实例的原型constructor指向的是NewTarget
// 会通过Person创建出来一个实例, 但是这个实例的原型constructor指向的Person
Reflect.construct(Super, arguments, NewTarget);

    if (hasNativeReflectConstruct) {
      var NewTarget = _getPrototypeOf(this).constructor;
      result = Reflect.construct(Super, arguments, NewTarget);
    } else {
      result = Super.apply(this, arguments);
    }
    return _possibleConstructorReturn(this, result);
  };
}

function _possibleConstructorReturn(self, call) {
  if (call && (_typeof(call) === "object" || typeof call === "function")) {
    return call;
  } else if (call !== void 0) {
    throw new TypeError(
      "Derived constructors may only return object or undefined"
    );
  }
  return _assertThisInitialized(self);
}

function _assertThisInitialized(self) {
  if (self === void 0) {
    throw new ReferenceError(
      "this hasn't been initialised - super() hasn't been called"
    );
  }
  return self;
}

function _isNativeReflectConstruct() {
  if (typeof Reflect === "undefined" || !Reflect.construct) return false;
  if (Reflect.construct.sham) return false;
  if (typeof Proxy === "function") return true;
  try {
    Boolean.prototype.valueOf.call(
      Reflect.construct(Boolean, [], function () {})
    );
    return true;
  } catch (e) {
    return false;
  }
}

function _getPrototypeOf(o) {
  _getPrototypeOf = Object.setPrototypeOf
    ? Object.getPrototypeOf
    : function _getPrototypeOf(o) {
        return o.__proto__ || Object.getPrototypeOf(o);
      };
  return _getPrototypeOf(o);
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

function _defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false;
    descriptor.configurable = true;
    if ("value" in descriptor) descriptor.writable = true;
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  return Constructor;
}

var Person = /*#__PURE__*/ (function () {
  function Person(name, age) {
    _classCallCheck(this, Person);

    this.name = name;
    this.age = age;
  }

  _createClass(Person, [
    {
      key: "running",
      value: function running() {
        console.log(this.name + " running~");
      }
    }
  ]);

  return Person;
})();

var Student = /*#__PURE__*/ (function (_Person) {
  // 实现之前的寄生式继承的方法(静态方法的继承)
  _inherits(Student, _Person);

  var _super = _createSuper(Student);

  function Student(name, age, sno) {
    var _this;

    _classCallCheck(this, Student);

    // Person不能被当成一个函数去调用 因为父类有判断 不能传入一个函数进去
    // Person.call(this, name, age)


    // 创建出来的对象 {name: , age: }
    _this = _super.call(this, name, age);
    _this.sno = sno;
    // {name: , age:, sno: }
    return _this;
  }

  _createClass(Student, [
    {
      key: "studying",
      value: function studying() {
        console.log(this.name + " studying~");
      }
    }
  ]);

  return Student;
})(Person);


var stu = new Student()