es6 class解析
直入主题。源代码如下:
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
- 给构造函数的原型设置属性(原型属性)
- 给构造函数本身设置属性(静态属性)
- 禁止修改 构造函数的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;
}
第二步执行:
_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部分
- Object.create(superClass && superClass.prototype);
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
也就是说这里生成了一个空对象{},空对象的__proto__是父类的.prototype.
也就是{}.__proto__ = { constructor: f A() }
- { constructor: { value: subClass, writable: true, configurable: true } }
如果该参数被指定且不为 undefined,将为新创建的对象添加指定的属性值和对应的属性描述符。
这里给上面创建的空对象添加constructor属性,值是f B(),并且设置constructor可修改/删除,不可被枚举
就变成了这样{ constructor: f B() }.__proto__ = { constructor: f A() }
- 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;
}
result
有值,并且是object
或者function
时返回result
result
是基本类型时报错- 否则返回B对象
_defineProperty(_assertThisInitialized(_this), "bName", "b");
给B对象设置class中定义好的属性_this.bAge = bAge;
执行constructor
中的this.bAge = bAge
返回B对象return _this;
es6 class解析的更多相关文章
- [ES6深度解析]15:模块 Module
JavaScript项目已经发展到令人瞠目结舌的规模,社区已经开发了用于大规模工作的工具.你需要的最基本的东西之一是一个模块系统,这是一种将你的工作分散到多个文件和目录的方法--但仍然要确保你的所有代 ...
- react native 中es6语法解析
react native是直接使用es6来编写代码,许多新语法能提高我们的工作效率 解构赋值 var { StyleSheet, Text, View } = React; 这句代码是ES6 中新增的 ...
- ES6深度解析3:Generators
介绍ES6 Generators 什么是Generators(生成器函数)?让我们先来看看一个例子. function* quips(name) { yield "hello " ...
- [ES6深度解析]12:Classes
我们将讨论一个老问题:在JavaScript中创建对象的构造函数. 存在的问题 假设我们想要创建最典型的面向对象设计的示例:Circle类.假设我们正在为一个简单的Canvas库编写一个Circle. ...
- [ES6深度解析]13:let const
当Brendan Eich在1995年设计了JavaScript的第一个版本时,他犯了很多错误,包括从那时起就成为该语言一部分的一些错误,比如Date对象和当你不小心将它们相乘时对象会自动转换为NaN ...
- [ES6深度解析]14:子类 Subclassing
我们描述了ES6中添加的新类系统,用于处理创建对象构造函数的琐碎情况.我们展示了如何使用它来编写如下代码: class Circle { constructor(radius) { this.radi ...
- Sublime插件支持Sass编译和Babel解析ES6 & .sublime-build文件初探
用Sublime Text蛮久了,配置配来配去的,每次换电脑都得重头再配过,奈何人老了脑子不中用了,得好好整理一些,下次换电脑就有得参考了.. 同事说,他的WebStorm简直太方便,自身集成了很多方 ...
- Sublime插件支持Sass编译和Babel解析ES6 & .sublime-build文件初探(转载自imwtr)
原文请看:http://www.cnblogs.com/imwtr/p/6010550.html 用Sublime Text蛮久了,配置配来配去的,每次换电脑都得重头再配过,奈何人老了脑子不中用了 ...
- es6语法快速上手(转载)
一.相关背景介绍 我们现在大多数人用的语法javascript 其实版本是ecmscript5,也是就es5.这个版本己经很多年了,且完美被各大浏览器所支持.所以很多学js的朋友可以一直分不清楚es5 ...
随机推荐
- 2、DTO(数据传输对象)
DTO:Data Transfer Object 即数据传输对象. 有些人会问这个DTO是干嘛的,不是已经有了Model实体类了么? 首先说一下,DTO是干嘛了.DTO的引入,应该说是伴随着分层架构设 ...
- k8s集群Job Pod 容器可能因为多种原因失效,想要更加稳定的使用Job负载,有哪些需要注意的地方?
k8s集群Job Pod 容器可能因为多种原因失效,想要更加稳定的使用Job负载,有哪些需要注意的地方? 面试官:"计数性Job默认完成模式是什么?Indexed模式如何发布自定义索引呢?& ...
- bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)
bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp) bzoj Luogu 对于一个01字符串,如果将这个字符串0和1取反后,再将整个串反过来和原串一 ...
- 图解CompletableFuture源码
前言 关于CompletableFuture源码解析部分,整体上感觉还是写比较难的,不过为了推广到团队还是要好好搞一下的,我还是希望大家看到这边文章能学到点什么,废话不多说开始吧. 属性部分 首先看属 ...
- 从零开始,开发一个 Web Office 套件(13):删除、替换已选中文字
这是一个系列博客,最终目的是要做一个基于 HTML Canvas 的.类似于微软 Office 的 Web Office 套件(包括:文档.表格.幻灯片--等等). 博客园:<从零开始, 开发一 ...
- web端,app端,小程序端测试差异详解
前置解释:1.单纯从功能测试的层面上来讲的话,APP 测试.web 测试和H5测试在流程和功能测试上是没有区别的2.Web项目或pc项目都是在电脑上进行测试的.常见的PC项目架构有BS架构和CS架构的 ...
- outlook配置osc地址(删除原账户重新配置)
方法二:使用手动配置邮箱(适用于标准化未入域机器) Step1:在"开始"菜单找到 "控制面板"并打开(或按键盘上的"Win"+" ...
- 【Java】这 35 个 Java 代码优化细节!
前言 代码 优化 ,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没 ...
- 使用docker-compose+nginx+uwsgi+django部署项目
(1)centos上下载docker + docker-compose (2)基础目录 (3)首先创建一个纯净的python+django+uwsgi的镜像,便于后期使用(也可不用创建,后期docke ...
- Django用mongoengine操作mongodb
最近在写Django项目,使用的是mongodb,虽然Django不支持NoSQL,但是mongoengine可以帮助我们像ORM一样在Django项目中去操作mongodb 推荐一个可视化工具 R ...