-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES6 系列之 Babel 是如何编译 Class 的(上) #105
Comments
mark |
1.
class Person {
// 实例属性
foo = 'foo';
constructor() {
}
}
2.
class Person {
constructor() {
this.foo='foo'
}
} 1和2编译出来是不一样的,你知道为什么要这样吗 |
@yibingxiong 这两个编译的结果是一样的 |
这是我之前写的demo,发现写到constructor里和外编译出来的是不一样的,但是看上去有没什么差别 |
最近一周从博主最开始的文章看到这里,虽然讨论的人越来越少了,但是质量仍然很高。这篇思路仍然非常清晰,收获良多,望博主继续加油。 |
同感,可能是年底拼绩效了吧 @ZhaZhengRefn |
@mqyqingfeng @yibingxiong 用Babel官网提供的 Try it out来试验的时候,写在 |
@jawil,当年热火朝天的讨论js |
讲得太通透了,解惑了好多平时开发时的语塞之处。 |
谢谢大佬分享,小白受益匪浅。 |
即便是三年前的文章,到现在还是受益匪浅🐨 |
吃透js,再来嚼几篇,可以说很有帮助,几个专题的文章质量都很高,写的很用心! |
前言
在了解 Babel 是如何编译 class 前,我们先看看 ES6 的 class 和 ES5 的构造函数是如何对应的。毕竟,ES6 的 class 可以看作一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
constructor
ES6 中:
对应到 ES5 中就是:
我们可以看到 ES5 的构造函数 Person,对应 ES6 的 Person 类的 constructor 方法。
值得注意的是:类的内部所有定义的方法,都是不可枚举的(non-enumerable)
以上面的例子为例,在 ES6 中:
然而在 ES5 中:
实例属性
以前,我们定义实例属性,只能写在类的 constructor 方法里面。比如:
然而现在有一个提案,对实例属性和静态属性都规定了新的写法,而且 Babel 已经支持。现在我们可以写成:
对应到 ES5 都是:
静态方法
所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上 static 关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
ES6 中:
对应 ES5:
静态属性
静态属性指的是 Class 本身的属性,即 Class.propName,而不是定义在实例对象(this)上的属性。以前,我们添加静态属性只可以这样:
因为上面提到的提案,现在可以写成:
对应到 ES5 都是:
new 调用
值得注意的是:类必须使用 new 调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用 new 也可以执行。
getter 和 setter
与 ES5 一样,在“类”的内部可以使用 get 和 set 关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
对应到 ES5 中:
Babel 编译
至此,我们已经知道了有关“类”的方法中,ES6 与 ES5 是如何对应的,实际上 Babel 在编译时并不会直接就转成这种形式,Babel 会自己生成一些辅助函数,帮助实现 ES6 的特性。
我们可以在 Babel 官网的 Try it out 页面查看 ES6 的代码编译成什么样子。
编译(一)
ES6 代码为:
Babel 编译为:
_classCallCheck 的作用是检查 Person 是否是通过 new 的方式调用,在上面,我们也说过,类必须使用 new 调用,否则会报错。
当我们使用
var person = Person()
的形式调用的时候,this 指向 window,所以instance instanceof Constructor
就会为 false,与 ES6 的要求一致。编译(二)
ES6 代码为:
Babel 编译为:
编译(三)
ES6 代码为:
对应到 ES5 的代码应该是:
Babel 编译后为:
我们可以看到 Babel 生成了一个 _createClass 辅助函数,该函数传入三个参数,第一个是构造函数,在这个例子中也就是 Person,第二个是要添加到原型上的函数数组,第三个是要添加到构造函数本身的函数数组,也就是所有添加 static 关键字的函数。该函数的作用就是将函数数组中的方法添加到构造函数或者构造函数的原型中,最后返回这个构造函数。
在其中,又生成了一个 defineProperties 辅助函数,使用 Object.defineProperty 方法添加属性。
默认 enumerable 为 false,configurable 为 true,这个在上面也有强调过,是为了防止 Object.keys() 之类的方法遍历到。然后通过判断 value 是否存在,来判断是否是 getter 和 setter。如果存在 value,就为 descriptor 添加 value 和 writable 属性,如果不存在,就直接使用 get 和 set 属性。
写在后面
至此,我们已经了解了 Babel 是如何编译一个 Class 的,然而,Class 还有一个重要的特性就是继承,Class 如何继承,Babel 又该如何编译,欢迎期待下一篇《 ES6 系列之 Babel 是如何编译 Class 的(下)》
ES6 系列
ES6 系列目录地址:https://github.com/mqyqingfeng/Blog
ES6 系列预计写二十篇左右,旨在加深 ES6 部分知识点的理解,重点讲解块级作用域、标签模板、箭头函数、Symbol、Set、Map 以及 Promise 的模拟实现、模块加载方案、异步处理等内容。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
The text was updated successfully, but these errors were encountered: