我用JavaScript 編程很多年了,寫了大量的JavaScript代碼,即便是我這樣的經歷,但我仍然還在努力地去寫出更優美的JavaScript代碼,在這篇文章中,我將探索爲什麼寫出漂亮的JavaScript代碼是如此困難,如何使用CoffeScript(一種簡約且能編譯成JavaScript的語言)改善它。
什麼是優美的代碼?
我想從個人觀點來聲明如何定義優美代碼
1、優美的代碼是使用更少的代碼解決問題;
2、優美的代碼是可讀而且易理解的
3、優美的代碼是一段既沒有什麼可以需要添加也沒有什麼多餘的可以去掉代碼(就像偉大的的設計)
4、最短長度是優美代碼的另外一個方面,並不是以此爲作爲目標或者權衡
所以對我來說,優美的代碼是最小代碼化、可使用、易讀的綜合效應。
一段優美JavaScript代碼的例子:
以斐波納契函數舉例來說,這個函數對絕大多數程序員來是應該知道的。這裏有一個談不上漂亮的實現,因爲代碼缺乏結構化,而且使用了很多沒必要的冗長代碼:
1
2
3
4
5
6
7
8
9
10
11
|
function f(n) { var s= 0; if (n == 0) return (s); if (n == 1) { s += 1; return (s); } else { return (f(n - 1) + f(n - 2)); } } |
這裏是另外一個版本的實現,我發現了更多優雅和優美之處,尤其是如果你熟悉單行的if else的話(三目條件運算):
1
2
|
function fib(n) { return n<2 ? n : fib(n-1) + fib(n-2)} |
同樣優美的一段碼,代碼的行數並不見得那麼重要
1
2
3
4
|
function fib(n) { if (n < 2) return n return fib(n-2) + fib(n-1)} |
JavaScript的毛病:
我認爲JavaScript的一個主要問題就是它那令人困惑的混雜多種不同語言的模式: JavaScript是函數式語言 JavaScript是面向對象的語言,但它是基於原型的 JavaScript是動態的非常接近於Lisp而不是C/Java,但是有C/Java的語法 JavaScript的名字就很讓人疑惑,但是和Java沒有半點關係 這種語言有特性危機,程序員嘗試強加範式到JavaScript中,但這並不是什麼好主意,因爲JavaScript不是Java,不是Sheme,也不是Python,就像其它語言一樣有自己的強項和弱項。
同時,JavaScript草率的設計和糟糕的決策表現在this,像this的動態域、用於繼承的語法,由於考慮到向後兼容的原因修復這些問題非常困難。這裏是一個很好的引用來自於JavaScript的創造者,亮點在JavaScript誕生的所處的環境:“JavaScript聽起來像Java,僅此而已,像是Java的啞巴小兄弟,但是我不得不在十天完成或者比JavaScript更糟糕的事情會發生”— Brendan Eich
CoffeeScript:全新的方式寫出更好的JavaScript
CoffeeScript是一種精緻的語言,能編譯成JavaScript。它的目的是用簡單的方法揭示JavaScript優秀的部分。
CoffeeScript不會終結你的JavaScript代碼
我喜歡CoffeeScript的原因之一是它能編譯成JavaScript,這就意味着我可以重用我當前所有的JavaScript代碼,我不需要重寫任何代碼到CoffeeScript,這是一筆偉大的交易,尤其是因爲我們的Wedoist JavaScript代碼庫非常龐大,要是重寫成另一種語言夠你花上數月的時間。 CoffeeScript同樣是一種迷你型的JavaScript,就像是被改善JavaScript版本,糟糕的部分被替換掉了。同時它的語法從C/Java語言換成了Ruby或者是Python(棒極了,因爲JavaScript 更接近於Ruby、Python而不是C或者Java)。
CoffeeScript是怎麼樣編譯成JavaScript
爲了闡述編譯,我們舉一例子,看他是怎麼工作的。 CoffeeScript代碼:
1
2
|
square = (x) -> x * x cube = (x) -> square(x) * x |
編譯成JavaScript代碼:
1
2
3
4
5
6
7
|
var cube, square; square = function (x) { return x * x; }; cube = function (x) { return square(x) * x; }; |
正如你從上例中看到的CoffeeScript和JavaScirpt的映射非常的直接。在另外一個網站你可以發現很多例子CoffeeScript如何編譯成JavaScript。
CoffeeScript:重寫示例
爲了給你一種CoffeeScript的感覺,這裏是個小JavaScript例子,我將重寫成CoffeeScript。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
get: function (offset, callback, limit) { var self = this ; var data = { project_id: Projects.getCurrent().id, limit: limit || this .default_limit } if (offset) data.offset = Calendar.jsonFormat(offset, true ); this .ajax.getArchived(data, function (data) { if (!offset) self.setCache(data); callback(data); }); } |
CoffeeScript看起來像這樣:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
get: (offset, callback, limit) => data = project_id: Projects.getCurrent().id limit: limit or @default_limit if offset data.offset = Calendar.jsonFormat(offset, true ) @ajax.getArchived(data, (data) => if !offset @setCache(data) callback(data) ) |
如你所見,兩者看起來非常相似,但是我的觀點是CoffeeScript看起來更輕快,因爲所有非必須的語法被移除僅保留了必須的元素。
現在讓我們來看看CoffeeScript的亮點:
亮點一:繼承更簡單
JavaScript有很強的繼承系統,但是語法很恐怖,CoffeeScript修復了用一種很優雅的繼承系統模擬其它很多語言中類和繼承機制:
1
2
3
4
5
6
7
8
9
10
|
class Animal constructor: (@name) -> move: (meters) -> alert @name + " moved " + meters + "m." class Snake extends Animal move: -> alert "Slithering..." super 5 |
亮點二:數組的迭代
我喜歡Python中的列表推導在CoffeeScript也有
1
2
|
list = [1, 2, 3, 4, 5] cubes = (math.cube num for num in list) |
數組切片:
1
|
copy = list[0...list.length] |
數組迭代:
1
|
countdown = (num for num in [10..1]) |
亮點三:字符串迭代
對於字符創的插入,CoffeeScript借用了Ruby的語法,它能簡單的構造字符串。
1
2
|
author = "Wittgenstein" quote = "A picture is a fact. -- #{ author }" |
允許多行的字符串:
1
2
3
|
mobyDick = "Call me Ishmael. Some years ago - never mind how long precisely -- having little or no money in my purse, and nothing particular..." |
亮點四:綁定this
this 關鍵字在JavaScript中部分的被破壞,因爲他的動態域,CoffeeScript修復了這些,如果你使用=>關鍵字(它自動爲你綁定this或者@)
1
2
3
4
5
6
7
|
Account = (customer, cart) -> @customer = customer @cart = cart $( '.shopping_cart' ).bind( 'click' , (event) => @customer.purchase @cart ) |
探索CoffeeScript
我僅僅抓住CoffeeScript的表面所提供的一些東西,更多細節請從他們的站點提取以及帶有註釋的源代碼。
我仍然在探索CoffeeScript,目前爲止這是我最喜歡的語言,榮譽屬於Jeremy Ashkenas。快樂的編程,我也希望你可以試一把CoffeeScript。