我用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。