直入主题。源代码如下:

class A{
aName = 'A'
constructor(aAge){
this.aAge = aAge
}
static aStatic = 'aStatic'
}
class B extends A{
bName = 'b'
constructor(bAge){
super()
this.bAge = bAge
}
static bStatic = 'bStatic'
} var b = new B;

使用babel转换后的代码如下:

"use strict";

// typeof
function _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 },
});
Object.defineProperty(subClass, "prototype", { writable: false });
if (superClass) _setPrototypeOf(subClass, superClass);
}
// 设置原型 setPrototypeOf
function _setPrototypeOf(o, p) {} function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
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;
} // 是否支持 Reflect.construct
function _isNativeReflectConstruct() {} // 获取原型 getPrototypeOf
function _getPrototypeOf(o) {} // 定义属性
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);
}
}
// 给prototype设置属性 / 设置static属性 / 禁止修改prototype
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", { writable: false });
return Constructor;
} // 检查 <不能将类作为函数调用>
function _classCallCheck(instance, Constructor) {} // 设置属性
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true,
});
} else {
obj[key] = value;
}
return obj;
} var A = /*#__PURE__*/ _createClass(function A(aAge) {
_classCallCheck(this, A); _defineProperty(this, "aName", "A"); this.aAge = aAge;
}); _defineProperty(A, "aStatic", "aStatic"); var B = /*#__PURE__*/ (function (_A) {
_inherits(B, _A); var _super = _createSuper(B); function B(bAge) {
var _this; _classCallCheck(this, B); _this = _super.call(this); _defineProperty(_assertThisInitialized(_this), "bName", "b"); _this.bAge = bAge;
return _this;
} return _createClass(B);
})(A); _defineProperty(B, "bStatic", "bStatic"); var b = new B();

流程图如下:

第一步会执行到这一行:

var A = /*#__PURE__*/ _createClass(function A(aAge) {

进入_createClass, 执行结束后返回处理过的 function A

  1. 给构造函数的原型设置属性(原型属性)
  2. 给构造函数本身设置属性(静态属性)
  3. 禁止修改 构造函数的prototype
  4. 最后返回构造函数本身
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", { writable: false });
return Constructor;
}

第二步执行:

_defineProperty(A, "aStatic", 'aStatic');

在这里给A设置aStatic=aStatic.

当key在obj中存在时,修改它的value,并且设置为可枚举,可删除,可修改

否则在obj中新增value.

// 设置属性
function _defineProperty(obj, key, value) {
if (key in obj) {
// 修改
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true,
});
} else {
// 新增
obj[key] = value;
}
return obj;
}

第三部执行

var B = /*#__PURE__*/ (function (_A) {

这里实现了原型继承和方法继承

_inherits(B, _A);

  subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: { value: subClass, writable: true, configurable: true },
});

这里可以拆分成3部分

  1. Object.create(superClass && superClass.prototype);
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

也就是说这里生成了一个空对象{},空对象的__proto__是父类的.prototype.

也就是{}.__proto__ = { constructor: f A() }
  1. { constructor: { value: subClass, writable: true, configurable: true } }
如果该参数被指定且不为 undefined,将为新创建的对象添加指定的属性值和对应的属性描述符。

这里给上面创建的空对象添加constructor属性,值是f B(),并且设置constructor可修改/删除,不可被枚举

就变成了这样{ constructor: f B() }.__proto__ = { constructor: f A() }
  1. subClass.prototype =
这里给B设置原型

相当于B.prototype = { constructor: f B() }.__proto__ = { constructor: f A() }

到这里,原型继承就实现成功了.

Object.defineProperty(subClass, "prototype", { writable: false });

设置B的prototype不可写

if (superClass) _setPrototypeOf(subClass, superClass);

这里实现了方法的继承,B.__proto__ = A

function的寄生组合继承是没有上面一步的.只有class extends才有.

var _super = _createSuper(B);

判断了环境是否支持Reflect.construct,返回_createSuperInternal闭包给_super变量

return _createClass(B);

同上 _createClass A

_defineProperty(B, "bStatic", "bStatic");

同上

第四步执行 new

var b = new B();

先执行 function B(bAge) { 里面的内容

检查是否为function _classCallCheck(this, B);

调用上面的_super函数, _this = _super.call(this); ,执行 _createSuperInternal

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

通过 Reflect.construct 或者 Super.apply 得到实例对象.接下来将 this(也就是f B())result 传递给 _possibleConstructorReturn

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;
}
  1. result有值,并且是object或者function时返回result
  2. result是基本类型时报错
  3. 否则返回B对象

_defineProperty(_assertThisInitialized(_this), "bName", "b");

给B对象设置class中定义好的属性_this.bAge = bAge;

执行constructor中的this.bAge = bAge

返回B对象return _this;

es6 class解析的更多相关文章

  1. [ES6深度解析]15:模块 Module

    JavaScript项目已经发展到令人瞠目结舌的规模,社区已经开发了用于大规模工作的工具.你需要的最基本的东西之一是一个模块系统,这是一种将你的工作分散到多个文件和目录的方法--但仍然要确保你的所有代 ...

  2. react native 中es6语法解析

    react native是直接使用es6来编写代码,许多新语法能提高我们的工作效率 解构赋值 var { StyleSheet, Text, View } = React; 这句代码是ES6 中新增的 ...

  3. ES6深度解析3:Generators

    介绍ES6 Generators 什么是Generators(生成器函数)?让我们先来看看一个例子. function* quips(name) { yield "hello " ...

  4. [ES6深度解析]12:Classes

    我们将讨论一个老问题:在JavaScript中创建对象的构造函数. 存在的问题 假设我们想要创建最典型的面向对象设计的示例:Circle类.假设我们正在为一个简单的Canvas库编写一个Circle. ...

  5. [ES6深度解析]13:let const

    当Brendan Eich在1995年设计了JavaScript的第一个版本时,他犯了很多错误,包括从那时起就成为该语言一部分的一些错误,比如Date对象和当你不小心将它们相乘时对象会自动转换为NaN ...

  6. [ES6深度解析]14:子类 Subclassing

    我们描述了ES6中添加的新类系统,用于处理创建对象构造函数的琐碎情况.我们展示了如何使用它来编写如下代码: class Circle { constructor(radius) { this.radi ...

  7. Sublime插件支持Sass编译和Babel解析ES6 & .sublime-build文件初探

    用Sublime Text蛮久了,配置配来配去的,每次换电脑都得重头再配过,奈何人老了脑子不中用了,得好好整理一些,下次换电脑就有得参考了.. 同事说,他的WebStorm简直太方便,自身集成了很多方 ...

  8. Sublime插件支持Sass编译和Babel解析ES6 & .sublime-build文件初探(转载自imwtr)

    原文请看:http://www.cnblogs.com/imwtr/p/6010550.html   用Sublime Text蛮久了,配置配来配去的,每次换电脑都得重头再配过,奈何人老了脑子不中用了 ...

  9. es6语法快速上手(转载)

    一.相关背景介绍 我们现在大多数人用的语法javascript 其实版本是ecmscript5,也是就es5.这个版本己经很多年了,且完美被各大浏览器所支持.所以很多学js的朋友可以一直分不清楚es5 ...

随机推荐

  1. Ubuntu下使用C语言连接Mysql 8.0客户端教程

    Ubuntu下如何C语言程序连接MYSQL 8.0(全教程) 1. 安装GCC(略) 2. 安装mysql(本人使用的是最新MySQL 8.0版本) sudo apt install mysql-cl ...

  2. WIFI-Pumpkin无线钓鱼渗透

    WIFI-Pumpkin无线钓鱼渗透 描述 WiFi-Pumpkin是一款专用于无线环境渗透测试的完整框架,利用该工具可以伪造接入点完成中间人攻击,同时也支持一些其他的无线渗透测试功能.旨在提供更安全 ...

  3. 把项目发布到tomcat中的方式

    1.相对路径方式1:把项目index.html放在tomcat的webapps/ROOT下,浏览器访问地址:http://www.aaa.com:8080/index.html 2.相对路径方式2:在 ...

  4. 如何在不使用BasePACKAGE过滤器的情况下排除程序包?

    过滤程序包的方法不尽相同.但是弹簧启动提供了一个更复杂的选项,可以在不接触组件扫描的情况下实现这一点. 在使用注释@ SpringBootApplication时,可以使用排除属性. 请参阅下面的代码 ...

  5. Java 中的同步集合与并发集合有什么区别?

    同步集合与并发集合都为多线程和并发提供了合适的线程安全的集合,不过并发 集合的可扩展性更高.在 Java1.5 之前程序员们只有同步集合来用且在多线程并发 的时候会导致争用,阻碍了系统的扩展性.Jav ...

  6. 什么是持续集成(CI)?

    持续集成(CI)是每次团队成员提交版本控制更改时自动构建和测试代码的过程. 这鼓励开发人员通过在每个小任务完成后将更改合并到共享版本控制存储库来共 享代码和单元测试.

  7. 学习ELK日志平台(一)

    一.需求及基础: 场景: 1.开发人员不能登录线上服务器查看详细日志 2.各个系统都有日志,日志数据分散难以查找 3.日志数据量大,查询速度慢,或者数据不够实时 4.一个调用会涉及到多个系统,难以在这 ...

  8. Rust 中的数据布局--非正常大小的类型

    非正常大小的类型 大多数的时候,我们期望类型在编译时能够有一个静态已知的非零大小,但这并不总是 Rust 的常态. Dynamically Sized Types (DSTs) Rust 支持动态大小 ...

  9. 专家PID

    前面我们讨论了经典的数字PID控制算法及其常见的改进与补偿算法,基本已经覆盖了无模型和简单模型PID控制经典算法的大部.再接下来的我们将讨论智能PID控制,智能PID控制不同于常规意义下的智能控制,是 ...

  10. 阿里云、腾讯云、CentOS下的MySQL的安装与配置详解

    一. 安装 查看是否已安装 # 查看MySQL版本 mysql --version # 查看MySQL相关文件 whereis mysql 若已安装,卸载方法如下 # 卸载MySQL yum remo ...