从CoffeeScript的角度看ES6中的新特性
我成为一个CoffeeScript的粉丝超过两年了,我发现我用CoffeeScript生产率更高,低级错误更少,而且支持源码映射使得调试CoffeeScript很轻松。
最近我在使用Babel玩ES6,总体来讲,我还是很喜欢。这篇文章中,我会从CoffeeScript转换的角度把我对ES6的发现罗列出来,包括那些我喜欢的东西,看还有哪些是我不知道的。
强调语法缩进:好还是不好
我对CoffeeScript的语法缩进是爱恨交加,好的时候能带来很多的便利,但有时会导致严重的bug,这些bug浪费了你很多的时候,让你觉得依赖缩进的语法真的有些不值当。 ` 当你的代码块有一些嵌套语句,你又不小心地将其中的一个语句不正确地缩进了,就会导致这样的问题。看代码看多了,眼睛累了,这种事情就难免发生,但在CoffeeScript更容易发生。
当我开始写ES6代码时,我还不是很确定我应该怎么来写这样的代码。但我很快发现用花括号来写感觉很好。现在流行的编辑器普遍都支持花括号的匹配,你只要写开始的花括号,编辑器就可以自动生成结束的花括号。
`
当然我还是不用分号,如果你不需要分号,那就不要再用了,分号又难看,又要额外打一个字符,多余得很!
类的支持
ES6中类的支持简直完美,如果你从CoffeeScript转换过来,你会觉得很自然。我们通过一个简单的例子来比较一下他们的语法: ES6的类: `` I am an animal with ${this.numberOfLegs} legs` } }
class Monkey extends Animal { constructor(bananas) { super(2) this.bananas = bananas } toString() { let superString = super.toString() .replace(/an animal/, 'a monkey') return } } ```
CoffeeScript的类: ```coffeescript class Animal constructor: (@numberOfLegs) ->
toString: -> "I am an animal with #{@numberOfLegs} legs"
class Monkey extends Animal constructor: (@numberOfBananas) -> super(2)
toString: -> superString = super.toString() .replace(/an animal/, 'a monkey') "#{superString} and #{@numberOfLegs} bananas"
```
第一印象
你或许首先会注意到ES6比CoffeeScript冗余一些,原来在CoffeeScript中感觉很顺手的是构造器中实例变量的自动赋值的支持,就像这样: javascript constructor(numberOfLegs) { this.numberOfLegs = numberOfLegs } ```
当然这也不是什么大问题,如果都用明确的语法写出来,代码就会比较容易看。另外一个小的缺失点是不能用@快捷方式来做这个事情,原来做ruby的话,会感觉这种方式还是挺好用的。一般来说,这些地方我也感觉比较自然,我实际上还喜欢ES6的定义方法的语法方式。
super的使用
ES6中super处理的方式有点难以理解,CoffeeScript中用Ruby的方式来处理super(就是发一个消息给同名的超类方法),但是在ES6中,你只能在构造函数中使用裸super。ES6使用一种更加传统的类似JAVA的方式,也就是super是超类实例的引用。
如何Return
CoffeeScript中我们使用隐式的返回来构建像这样的漂亮代码: `
你调用foo()的时候,这样可以让foo返回。ES6没有这样的方式,需要我们使用return关键字返回:
`
就像我们上面看到的那样,这样做一般来说是好事,但我发现我有时会忘记加上return,结果到处都得到了不期望的undefined。我就曾遇到过一个关于Arrow函数的异常,你得到了一个隐式的返回,就像这样: javascript array.map( x => { return x * 10 }) ``` 然而,这样做还是有意义的。原因在于既然你用花括号,你是有多行语句的,如果你有多行语句,使用return会使你返回的内容就变得清晰。
ES6类语法的好处
我们已经看到了CoffeeScript在定义类的时候的几个语法上的小技巧,但ES6也有一些它自己的小技巧:
Getters和Setters
如下面例子所示,ES6通过getters和setters,对通过getters和setters进行封装有强大的支持:
` 由于有getter,我们在访问bananaStore.bananas的时候,它只会返回ripe的香蕉。但在CoffeeScript中,就需要通过一个类似bananaStore.getBananas()的getter方法来实现这样的功能。这样一点都不自然,因为在javascript中我们一直都是直接访问属性的。这也让开发的时候感到困惑,我们需要如何访问每个属性,到底用.bananas呢还是用getBananas()?
在清除设置的数据,或者置入无效的数据时抛出异常的时候,Setter一样是有用的,就像上面toy例子上所示的。对于有Ruby背景的人来说,这是很熟悉的。
我个人不认为这意味着你要疯狂地在所有的地方都使用setters和getters。如果你通过getters和setters的方式封装实例变量,你觉得比较好,那你就尽管用这种方式。但如果你只是一个布尔变量,类似于isEditable,就没有必要了。因为你直接访问也不会引起什么坏处,为简单期间,那就直接访问好了。
静态方法
ES6支持静态方法,这样我们就可以玩这样的小技巧了: ` 这样,如果你不喜欢写new Foo(),你现在就可以写成Foo.new(). new本来是一个关键字,却被用作函数名,看上去似乎不太好,但在Node.js以及新版的浏览器中,这种方式跑得很好。生产环境下你很可能不想这样用。
不幸的是,因为在ES6中不支持静态属性,如果你想定义类常量,并在静态方法中访问他们,你需要这样做:
`
是不是感觉怪怪的?
ES7中有人建议实现陈述式实例和类属性,这样我们可以这样写:
` 看起来要更好一些。
在CoffeeScript中做起来就比较好:
```coffeescript class Foo @ROOT_PATH: '/foo'
@imgPath: -> @ROOT_PATH
```
字符串插值
Javascript中终于可以做字符串插值了!
。从CoffeeScript和Ruby中走过来,这种语法看起来有些好玩。也许Ruby中字符”`“(数字1左边的字符)一般用来执行系统命令,也许Ruby用熟了,开始用起来很不爽。此外用美元符号给我感觉有点80的感觉($有点像8?),可能只有我有这个感觉吧,呵呵。
我想只是后向兼容性的考虑,于是不能实现CoffeeScript类型的字符串插值。就像这样"What a #{expletive} shame".
箭头函数
在CoffeeScript中箭头函数是理所当然的。ES6实现了大多数的类似于CoffeeScript中的箭头语法,这样我们可以写好看的短语句,我们也可以得到词典式。所以我们不需要像ES6中这样跳转:
` ES6中对等的写法是这样的:
```javascript doSomethingAsync().then( res => { this.foo(res) })
注意我忽略了回调函数的括号,ES6支持这样写。
对象语法
ES6中对象词法有重大的性能提升,他们能做所有的事情
动态属性名
我实际上没有意识到自从CoffeeScript 1.9.1 以来,直到写这篇文章,我们能这样做:
`
要是以前,你得这样写:
` ES6有一个替代的语法,我觉得很漂亮,但也算不上重大的进步:
`
这实际上是从CoffeeScript拿来的,但我之前一直没有用过。其实还是蛮有用的:
` 现在obj对象的内容是{ foo: 'foo', bar: 'bar' }。这种方式很有用,值得记住。
类能做的我都能做
Object literals能做类所能做的绝大多数的事情,甚至想这样的:
` 你为什么这样做我不关心,但现在你确实可以这样写了。你当然不能定义静态方法,因为这根本没有意义。
让你困惑的for循环
ES6中for循环可能会让经验丰富的CoffeeScript程序员引入内存方面的bug,因为ES6中的for-of与CoffeeScript中的for-in对应。
ES6
` CoffeeScript
```coffeescript for i of [1, 2, 3] console.log(i)
0
1
2
```
是否应该切换到ES6
我现在在做一个大型的Node.js工程,其中全部用的都是CoffeeScript,用起来感到很高兴,生产率也超高。ES6中唯一对我有吸引力的是getters和setters。
我现在用ES6还是感到有些痛苦,如果你使用最新的Node.js版本,那么你就可以使用所有的ES6特征,但如果你用老一些的版本,或者在浏览器中使用,就没有这么好玩了。是的,你可以使用Babel,但这样就需要将Babel集成到你的技术栈中。
我还会观察ES6一到两年,我希望在ES7中看到更好的东东。
我对ES6真正满意的是 “plain old JavaScript”像CoffeeScript一样便于使用,过去我在写Javascript工程的时候总是感到不爽,但用ES6的话就没有这个问题。
译自: What's New in ES6? Perspective of a CoffeeScript Convert