假如是我的话,我可能会这样去编译:
var Person = function () {
function Person() {
}
Person.prototype.getName = function () { return this.name };
return Person;
}();
因为我们以前就是这么写“类”的,那babel为什么要采用 Object.defineProperty这样的形式呢,用原型链有什么不妥呢?自然是非常的不妥的,因为ES6的一些语法是有其特定的语义的。比如:
类内部声明的方法,是不可枚举的,而通过原型链声明的方法是可以枚举的。这里可以参考下阮老师介绍
for...of的循环是通过遍历器(Iterator)迭代的,循环数组时并非是i++,然后通过下标寻值。这里依旧可以看下阮老师关于遍历器与for...of的介绍,以及一篇babel关于for...of编译的说明transform-es2015-for-of
所以,babel为了符合ES6真正的语义,编译类时采取了 Object.defineProperty来定义原型方法,于是导致了后续这些一系列问题。
眼尖的同学可能在我上述第二点中发的链接 transform-es2015-for-of中看到,babel其实是有一个 loose模式的,直译的话叫做宽松模式。它是做什么用的呢?它会不严格遵循ES6的语义,而采取更符合我们平常编写代码时的习惯去编译代码。比如上述的 Person类的属性方法将会编译成直接在原型链上声明方法。
这个模式具体的babel配置如下:

// .babelrc
{
"presets": [["env", { "loose": false }]]
}
同样的,我放个repl示例方便大家直接查看效果:
咦,如果我们真的不关心类方法能否被枚举,开启了 loose模式,这样是不是就没有副作用产生,就能完美tree-shaking类了呢?
我们开启了 loose模式,使用rollup打包,发现还真是如此! 传送门
然而不要开心的太早,当我们用Webpack配合UglifyJS打包文件时,这个Person类的IIFE又被打包进去了? What???
为了彻底搞明白这个问题,我搜到一条UglifyJS的issue: Class declaration in IIFE considered as side effect,仔细看了好久。对此有兴趣、并且英语还ok的同学,可以快速去了解这条issue,还是挺有意思的。我大致阐述下这条issue下都说了些啥。
issue楼主- blacksonic
好奇为什么UglifyJS不能消除未引用的类。
UglifyJS贡献者-kzc说,uglify不进行程序流分析,所以不能排除有可能有副作用的代码。
楼主:我的代码没什么副作用啊。要不你们来个配置项,设置后,可以认为它是没有副作用的,然后放心的删了它们吧。
贡献者:我们没有程序流分析,我们干不了这事儿,实在想删除他们,出门左转 rollup 吼吧,他们屌,做了程序流分析,能判断到底有没有副作用。
楼主:迁移rollup成本有点高啊。我觉得加个配置不难啊,比如这样这样,巴拉巴拉。
贡献者:欢迎提PR。
楼主:别嘛,你们项目上千行代码,我咋提PR啊。我的代码也没啥副作用啊,您能详细的说明下么?
贡献者:变量赋值就是有可能产生副作用的!我举个例子:
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-59797-3.html
而且要严正表明
0