[关闭]
@zhouweicsu 2015-04-15T16:49:41.000000Z 字数 3725 阅读 708

【译】CoffeeScript万岁!ES6万岁!

CoffeeScript


原文链接:Long Live CoffeeScript and Long Live ES6

显然ES6对ES5来说是一个巨大的改进,并且6to5这类工具使我们可以开始使用这些酷毙了的特性。我之前阅读了Blake Williams的一篇文章Replace CoffeeScript with ES6 (【译】用ES6替代CoffeeScript) ,文章对ES6如何解决许多CoffeeScript解决了的问题做了一个非常好的总结;然而,我想就Blake的几个观点做点评论,并谈谈为什么我将会继续使用CoffeeScript。

ES6中的类(还有其他ES6中的语法变化)与CoffeeScript的非常相似。为了支持ES5中不兼容的浏览器(例如IE8-),因此,我们仍然不能真正的使用getters/setters,所以忽略这些,比较如下:

  1. class Person
  2. constructor: (@firstName, @lastName) ->
  3. name: ->
  4. "#{@firstName} #{@lastName}"
  5. setName: (name) ->
  6. [@firstName, @lastName] = name.split " "
  7. @defaultName: ->
  8. "Unidentified Person"
  9. blake = new Person "Blake", "Williams"
  10. blake.setName "Blake Anderson"
  11. console.log blake.name()

vs

  1. class Person {
  2. constructor(firstName, lastName) {
  3. this.firstName = firstName;
  4. this.lastName = lastName;
  5. }
  6. name() {
  7. return `${this.firstName} ${this.lastName}`;
  8. }
  9. setName(name) {
  10. [this.firstName, this.lastName] = name.split(" ");
  11. }
  12. static defaultName() {
  13. return "Unidentified Person"
  14. }
  15. }
  16. var blake = new Person("Blake", "Williams");
  17. blake.setName("Blake Anderson");
  18. console.log(blake.name());

我绝对喜欢ES6的风格——无需逗号,不需要到处写function;但是我是“write less code”派,所以我还是选择前者。然而,这真的是个人品味问题,如果你喜欢this.而不是@,喜欢添加所有额外的大括号,那么这毫无疑问你是支持Blake的观点的,认为ES6是一个更好的选择。

虽然我能理解为什么ES6允许你调用父对象的一种不同的方法,但是我还是得说我更喜欢CoffeeScript中super的实现。


字符串插值

很显然ES6与CoffeeScript中的字符串插值非常相似;CoffeeScript的字符串插值使用常规的“strings”,ES6使用`包裹字符串(吐槽:这导致在写Markdown的时候相当烦人)。CoffeeScript使用#{var},ES6使用${var}。这些点都大同小异。

真正突出的差别是对空白的处理——ES6(或者至少是6to5工具)会保留所有位于` 之间的空格(包括换行和缩进),CoffeeScript的处理时位于简单"中的字符串会将所有空白合并成一个空格,若是位于"""之间的块级字符串则保留所有空格用来缩进,在我看来这两者的行为都是值得保留的,然后ES6的处理却没有,举个栗子:

  1. (function() {
  2. function foo(bar, val) {
  3. if (bar) {
  4. var str = `This is quite a long first line
  5. so I wrap it to a second line and then
  6. append the value ${val}`;
  7. }
  8. }
  9. })();

通过6to5 REPL的转化输出是:

  1. var str = "This is quite a long first line\n so I wrap it to a second line and then\n append the value " + val;

等价的CoffeeScript代码:

  1. do ->
  2. foo = (bar, val) ->
  3. if bar
  4. str = "This is quite a long first line
  5. so I wrap it to a second line and then
  6. append the value #{val}";
  7. str2 =
  8. """
  9. This is quite a long first line
  10. so I wrap it to a second line and then
  11. append the value #{val}
  12. """

编译之后:

  1. var str = "This is quite a long first line so I wrap it to a second line and then append the value " + val;
  2. var str2 = "This is quite a long first line\nso I wrap it to a second line and then\nappend the value " + val;

我实在想不出一个能让我选择6to5的理由。


胖箭头,默认参数

这两项是对JS语法的杰出扩展,ES6的表现与CoffeeScript大致相同,只有少量语法不同。


参数列表(splats)

另一个杰出扩展,我发现参数列表(splats)这个技能在参数列的中间非常 有用,尤其是在Node.js风格的回调函数的情况下,回调函数可以自动弹出然后退出。举个栗子:

  1. # Splat dereferencing
  2. names = ["Alice", "Belinda", "Catherine", "Davidson"]
  3. [firstName, middleNames..., lastName] = names
  4. # Splat function args preserving callback
  5. foo = (fn, args..., callback) ->
  6. results = (fn arg for arg in args)
  7. process.nextTick ->
  8. callback null, results
  9. double = (a) -> a * 2
  10. foo double, 80, 60, 40, (err, results) ->
  11. console.log results

遗憾的是,ES6中只允许splats位于参数列的最后,如果需要你只能使用pop()函数来取回调(或姓氏),让你的代码变得很长,让你选择更多变量名(我们都很讨厌选变量名,不是吗?):

  1. var names = ["Alice", "Belinda", "Catherine", "Davidson"];
  2. var firstName, middleNames, lastName, rest;
  3. [firstName, ...rest] = names;
  4. lastName = rest.pop();
  5. middleNames = rest;

构造/解构函数

我必须承认我很喜欢ES6的一个特性,就是在你写var [first, , last] = [1, 2, 3]赋值语句时可以使用真正的空格,但是用下划线或其他类似字符也可以是一种解决方案。

ES6中对象的构造/解构函数与CoffeeScript几乎一样(var {a, b} = {a: 1, c:3}var {foo: a, bar: b} = {foo: 1, baz: 3}, 还有var c = {a, b}),但当引用当前对象的属性时,CoffeeScript的做法更好,如c = {@a, @b}var c = {a: this.a, b: this.b})。


一些我希望CoffeeScript拥有的ES6特性

尝试将CoffeeScript描绘成一个完美的语言是不明智的,它显然不是,它也有缺点,下面给出一个CoffeeScript中没有但ES6(甚至ES3)中有的特性列表:


结束语

总的来说ES6对JavaScript来说是一个伟大的飞跃,非常感谢所有让这些成为可能的开发者。以上未提及的许多ES6新增的特性都没有涉及语法变化,因此CoffeeScript也可以直接使用,例如Proxies,WeakMaps等。(我们现在甚至还有yield)。

我还是会坚持选择使用CoffeeScript的语法,因为它简明易读,大大提高了我的工作效率。我也很难放弃各种CoffeeScript的语法糖,例如:object?.property,当object是null或者undefined的时候不会报错;a ?= ba ||= b等;隐式返回;unless;升级版switch;范围缩写[a..b];array/string利用范围arr[2..6]来切割;for own k, v of obj;链式比较 a < b < c;块级正则表达式;还有更多!

CoffeeScript万岁!ES6万岁!

译者 @zhouweicsu
2015 年 4月 15日

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注