從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