从CoffeeScript的角度看ES6中的新特性

jopen 8年前

我成为一个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

来自: http://www.kiford.com/a/WZ0111160VZQZGST