探索 Class 底层原理

Posted jweboy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探索 Class 底层原理相关的知识,希望对你有一定的参考价值。

ECMAScript6 实现了 class ,实际上它是一个语法糖,但是它的出现能使 JS 编码更清晰,更接近 面向对象编程

实现原理

首先我们来看 ES6class 的实现和 ES5 构造函数的实现,两者相比较不难看出 constructor 其实就是构造方法,指向 ES5 的构造函数,那么 class 本身指向的是构造函数,换言之底层依旧是构造函数。

ES6

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

  static run() {
    console.log("run");
  }
  say() {
    console.log("hello!");
  }
}

ES5

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.say = function () {
  console.log("hello!");
};

Person.run = function () {
  console.log("run");
};

babel 编译分析

通过 babel 编译器将 ES6 代码 转换成 ES5 代码之后(代码转换可以试用 babel 官方在线工具),可得到这两个关键函数 _defineProperties_createClass,现在我们来一一解析说明。

...
var Person = /*#__PURE__*/ (function () {
  "use strict";

  function Person(name, age) {
    _classCallCheck(this, Person);

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

  _createClass(
    Person,
    [
      {
        key: "say",
        value: function say() {
          console.log("hello!");
        },
      },
    ],
    [
      {
        key: "run",
        value: function run() {
          console.log("run");
        },
      },
    ]
  );

  return Person;
})();

\\_createClass

_createClass 函数主要用于配置构造函数或构造函数原型上的公有函数和静态方法,并返回构造函数本身。

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

\\_defineProperties

_defineProperties 函数主要用于声明公有函数和静态方法的描述符,并将其挂载到当前的构造函数或构造函数原型。它接收两个参数 target() 和 props

  • target 指向当前的构造函数或构造函数原型
  • props 数组类型,指向公有函数和静态方法

在遍历数组时,我们可以看到 enumerable 默认是 false,也就是说 class 类上的内部属性默认是不可枚举的,不能使用 Object.keys 遍历,具体如下:

Object.keys(Person.prototype); // []
Object.keys(Person); // []

同时在遍历的时候还会判断当前描述符是否存在 value 值,如果存在就设置可写属性 writabletrue,反之就使用 getset 属性。在遍历的末尾,通过 Object.defineProperty 将描述符配置到当前的构造函数或构造函数原型上,至此就是 class 的基本实现了。

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

构造函数的区别

暂时性死区

class 不会声明提升,存在 暂时性死区,构造函数的本质是函数,函数声明会有提升作用。

// 

以上是关于探索 Class 底层原理的主要内容,如果未能解决你的问题,请参考以下文章

iOS底层原理类探索之cache分析

Spring注解原理探索(一)

iOS底层探索之类的结构(下)

OC底层原理探索-NSRunLoop

Java技术专题「原理分析系列」分析反射底层原理及基础开发实战

iOS底层原理之类,元类,根元类探索(上)