[原创翻译]哪一种JavaScript方案适合你?
声明:这是第一次翻译,肯定有很多不足的地方,希望提出改正。此篇文章由wuxu92根据zack Grossbart的英文文章原名《which JavaScript Recipe Is Right For You》进行翻译,整个译文带有我自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://coding.smashingmagazine.com/2012/12/14/which-javascript-recipe-is-right-for-you/以及作者相关信息 ——译者:wuxu92
哪一种JavaScript方案适合你?
作者:Zack Grossbart发表时间:2012-12-14
原文地址:http://coding.smashingmagazine.com/2012/12/14/which-javascript-recipe-is-right-for-you/
JavaScript被认为是从大到可怕到小到Web的汇编语言之间的任何事物,但是我们还是都在使用它。不管喜不喜欢JavaScript,每个人都承认JavaScript有一些严重的漏洞和许多其他的选择。
让我们从一些对JavaScript的基本否定开始吧。JavaScript没有为一些现代编程语言的基本特征提供好的答案,比如私有变量和私有函数,打包和模块化,标准的本地化机制,在编辑器中完成代码(code
completion in editors )。
当JavaScript失去很多特性的时候,这门语言的强动态性成为许多静态编程语言信徒的噩梦。比如下面的JavaScript代码都是正确的:
obj1
=
{
func1
:
function
()
{
return
"I'm function 1"
;
}
};
obj1
[
'func2'
]
=
function
()
{
return
"I'm function 2"
;
};
obj1
[
'fu'
+
'nc'
+
3
]
=
function
()
{
return
"I'm function 3"
;
}
var
f
=
'func4'
;
obj1
[
f
]
=
function
()
{
return
"I'm function 4"
;
}
alert
(
obj1
.
func2
());
alert
(
obj1
.
func3
());
alert
(
obj1
.
func4
());
大多数语言都支持动态代码加载,但是JavaScript不仅如此,js甚至鼓励这种行为。JavaScript有许多黑暗角落。你知道在JavaScript中两个数组相加的加过是空字符串吗,或者你知道[]+{}的结果是[object Object]而{}+[]的结果是0吗?Wat?!?
JavaScript使得写一些很不好都的代码是如此简单,所以(一些人认为)用JavaScript写大型的项目是不可能的.....除了Twitter, facebook, Google,和其他你听说过的上百个大型网站。
这些缺点每天都给我造成很多问题,但是我仍然非常喜爱JavaScript。用js写代码非常有意思,并且它远不止Web的汇编语言这么简单,汇编语言是几乎不能用手写甚至难读的:
C005 B7 80 04 STA A ACIA C008 86 11 LDA A C00A B7 80 04 STA A ACIA JavaScript写起来非常简单,如果我有一个button按钮,并且当有人点击它时我想知道,我能导入一个像jQuery一样的库,然后写一个click函数:$
(
'#myButton'
).
click
(
function
()
{
alert
(
'I was clicked'
);
});
估计你的祖母都能猜出这些代码的作用,这就是为什么JavaScript是一门好的第一编程语言,并且是一门好的原型语言。使用JavaScript程序把一个空白页变为一个运行的程序的速度不可思议的快。它们写起来很快,不需要编译器,并且允许你做任何你需要的事情。
这两种对JavaScript的观点很难调和:JavaScript是一种定义不明确的宽松语言设计导致它过早的满头白发(premature gray hair ),还是它是一个有趣的工作场所?答案是两者都是。
每次面对新的Web工程的时候,我们都面临这个选择:是写JavaScript呢,还是用其他语言?这篇文章会告诉你怎么选择。
JavaScript在不断的进步
JavaScript是当前最临行的客户端编程语言,现金已很难找到一个不运行JavaScript的网站,它随着一些非常优秀的库,像jQuery,Backbone还有其他许多,的出现已经走过漫长的岁月(come a long way )。JavaScript在小项目上轻松取胜,但是当项目和团队越来越大是,JavaScript就显得力不从心了。
每一个大型JavaScript项目都采用约定来补偿语言特性的缺乏。很简单的模式就是像使用一个下划线来标记私有函数,或者在参数前添加注释来表明参数希望的类型。
function
formatDate
(
/* Date */
d
)
{
var
day
=
d
.
getDate
();
var
month
=
d
.
getMonth
()
+
1
;
var
year
=
d
.
getFullYear
();
return
date
+
"-"
+
month
+
"-"
+
year
;
}
这些注释很有用,但是没有什么能阻止你向formatDate函数传递一个字符串,一个数字或者任何其他的东西。你不能强制执行一个编程惯例,在你的代码在生产环境运行并且失败之前,你永远都不知道约定被打破了。额外的想instanceOf的类型检测使得程序在失败时产生一个更有用的错误信息,但是它还是只在运行时才失败,而不是被编译器捕获。
像JSLint或者JSHint的工具能检测一些普通的格式问题,像当你在应该使用===的地方使用了==,但是它们不能定位大的问题。像RequireJS这样的库为JavaScript提供了一些对模块的支持,但是它还是只是一个约定。没有任何东西强制这些模式,你将花费无数的时间去追踪bugs,调试别人的JavaScript程序是一件非常无聊的事情。
程序员们都喜欢相处一些新的解决办法来解决存在的问题,但是对于JavaScript,貌似没有多少好的选择。
Google
网络工具组件(GWT)
Google做了用GWT替代JavaScript的第一次主要的努力。这个方法是写出Java程序然后编译为JavaScript。Java提供许多JavaScript没有的语言特性,并且编译器使得代码运行前可以多很多的检查。因为有好的编译器和UI库的加入,GWT似乎要接管整个(Web)世界。
但是,它没有。
GWT失败了(至少现在是的),但是它也有成功的地方。Java是一种很难书写的语言。它有许多复杂的地方,需要有深刻理解面向对象编程。
Java的复杂性大多数来自它要解决的难题。如果你过去有这些问题那将非常好办,但是如果没有,这杀伤力就太大了(That’s nice if you were going to have those problems, but overkill if you weren’t )。
GWT把Web的复杂性加在Java上面,它的定位也是不需要考虑浏览器或者HTML的Web编程。它生成的接口看起来笨重而且运行缓慢。它同时导致一些坏的反模式(anti-patterns)
令人沮丧的是有明显的迹象表明GWT是没有未来的~~.尽管Google仍然在维护它,但是它的社区正在缩小,控制Web世界的美梦也早就不复存在。甚至Google自身都从来没有真正的使用过GWT。Google所有的主要产品(搜索,Gmail,地图,日历,文档,Google+)都是用JavaScript写的。好吧...是JavaScript的一种,但是我们稍后会讨论它。
我个人仍在使用GWT,但是在一个新的项目使用它时,我总是质疑它。GWT激烈的改变了JavaScript的生态系统,它像把一艘航空母舰放上一个一角硬币一样难。
CoffeeScript
CoffeeScript团队并没有重新定义JavaScript,他们只是翻新了一下它。CoffeeScript增加了新的格式来改善JavaScript编程的日常困难,而没有彻底的改变这门语言。
下面的JavaScript
$
(
document
).
ready
(
function
()
{
alert
(
'Hello World!'
);
});
用CoffeeScript替代可以这样写:
$
(
document
).
ready
->
alert
'Hello World!'
;
一个普通的哲学观点是:写更少的代码以为着更少的bugs。CoffeeScript,通过删除需要声明的变量和使用空白缩进来代替大括号,简化了JavaScript格式。
CoffeeScript成长的很快,它被Ruby程序员喜爱而被其他暗恋花括号的人讨厌。CoffeeScript不是在页面运行时,也不是在构建步骤之前,编译为JavaScript。
CoffeeScript在JavaScript上做了许多语法改进,但是它还有两个主要的缺陷。第一个是不能直接编译CoffeeScript。浏览器不能原生支持运行CoffeeScript,所以你在经过编译的JavaScript中获得错误信息,然后再用这些信息去找源码中的错误。这意味着在没有深刻理解JavaScript之前,你很难写好一个CoffeeScript程序。
第二个主要缺陷CoffeeScript基本上只是JavaScript的不同语法。CoffeeScript意味着写更少的代码,但是作为一门编程语言,它并没有解决JavaScript的真正存在的问题。这仍然是我喜欢我的CoffeeScript而讨厌其他人的的原因(It’s still the case that I love my CoffeeScript and hate everyone else’s. )。
Google闭包工具
在CoffeeScript出现的同时,Google做了用Google闭包工具来改进JavaScript的尝试。Google尽量是GWT成为下一代占统治地位的Web技术,但是先默默的把闭包扫地出门(but it let Closure slip quietly out the door )。
闭包包含一个模板机制和一个包含很多组件的库,但是最有趣的部分是闭包编译器(Closure Compiler和闭包检测器(Closure Linter)。
闭包编译器(像YUI压缩机)先得到你的JavaScript然后压缩,这样的话可以加快产品下载和运行的速度。普遍的想法是用标准的JavaScript开发,然后编译并发布。
闭包编译器把下面的代码:
function
sayHello
()
{
alert
(
'Hello World!'
);
}
$
(
document
).
ready
(
function
()
{
sayHello
();
});
转变为
$
(
document
).
ea
(
function
(){
alert
(
"Hello World!"
)});
结果的可读性很不好,但是运行要快得多。
闭包编译器支持两种主要的模式:简单的和高级的。简单模式通过,去掉JavaScript代码中的注释和空白符,缩短变量名和做一些其他的安全的变化,来压缩代码。简单模式一般不会打破你的JavaScript代码,并且能够在编译的时候发现一些问题。
高级模式提供更好的压缩机制,但是,除非你事先计划好了,这是一个它打破你代码的好机会(but there’s a pretty good chance it will break your code unless you plan ahead. )。高级模式需要额外的信息告诉编译器哪些不应该删除。JavaScript的动态性使得编译器很难在没有帮助的情况下遵循代码树中的每一条路径(it tough for the compiler to follow every path in your code tree without some help ).
闭包工具同时引进了JSDoc标签,它会告诉编译器更多关于你的代码工作原理的信息。在普通的JavaScript中,你可能在应用中定义有三个状态的对象:
myProject
.
threeStates
=
{
TRUE
:
1
,
FALSE
:
-
1
,
MAYBE
:
0
};
你知道这是一个有这三种状态中的一个的枚举类型,但是编译器并不知道这些,你那些动态的添加第四个值的的队友也不知道。JSDoc让你明确这是怎么工作的:
/**
* Enum for my three states.
* @enum {number}
*/
myProject
.
threeStates
=
{
TRUE
:
1
,
FALSE
:
-
1
,
MAYBE
:
0
};
通过增加这写注释,你声明了这是一个枚举,并且它只包含数字,你把它定义为一个可以在其他地方使用的强类型。这些性质和闭包检测器(Closure linter )结合强制你这样写注释,同时你基本上重新定义了JavaScript。尽管看起来仍然像JavaScript,但却是一种强类型的语言了。
通过@type注释很容易看到:
/**
* The name of the user
* @type {string}
*/
var
name
=
'Zack'
;
JSDoc支持其他的注释,这些注释能控制从函数的返回值到谁能调用的所有事。添加一个模块加载器,闭包库通过把JavaScript转变为Java来指出(addresses)其中的大量缺点(the Closure library addresses a lot of the shortcomings of JavaScript, by turning it into Java )。
笨重的语法使得闭包工具看起来很像Java,使用相似的包装机制,有强大的编译器;这样做有好有坏,就像Java有好有坏一样。
Google并没有对闭包工具做太多的营销,但是把大量的工程移到那。Google的大多数产品都使用闭包。Google+就是彻底在闭包上建立的。
闭包社区正在成长壮大,但是Google之外的很多人仍然不熟悉它。闭包也要忍受需要向后兼容JavaScript。它的语法看起来很笨拙,并且只要多一些高级的JavaScript编程和面向对象程序员就能实现它。
一些人认为Web需要一门崭新的语言,所以Google继续扮演JavaScript腹黑友的形象:发明了Dart。
Dart
Dart完全用一种强类型的语言替代了JavaScript,它使用接口并且看起来很像是简化了的Java。
library hi
;
import
'dart:html'
;
main
()
{
query
(
'#status'
).
text
=
'Hi, Dart'
;
}
这个简单的“hello world”示例真是了包,导入和与Java语法类似的方法。
Dart能够编译成JavaScript,但是在浏览器上原生支持运行和调试能等到更好的性能。Google控制着Chrome浏览器,可能它会增加对Dart的原生支持.现在已经有一个在Windows上运行的特殊版本,但还不是所有的。
Chrome依赖于Webkit,它同时也支持这Apple的Safari浏览器。Webkit是一个开源的项目,它有三分之一的Google的人员,三分之一的Apple的人员,还有三分之一其他的人。Chrome团队希望Webkit能支持Dart,因为这样能让他们更加轻松,同时使得Safari也支持Dart。如果这成为事实的话,他们就可以宣传两款主流的浏览器都支持Dart,这会迫使其他浏览器也跟着改变。但是Safari团队不希望Web在一种由Google所有的新语言上运行,所以他们坚持不在Webkit中包含对Dart的原生支持。
这看起来其他的浏览器也不会支持Dart。这使你把Dart编译为JavaScript并且失去像集成调试器这样的好的功能。
Dart有许多技术上的优点,但却因为政治上的大分歧而黯然失色(it’s eclipsed by larger political problems).
一些非常聪明的Google人用Dart工作,并且有许多好的特性,但是它仍然只是Google哦一个发明并且没有标准化。它不是由一个社区开发的,这有理由让其他的供应商不信任它。
关于Dart有一件事是可以确定的:那就是未来不明确。尽管一个预览版(V 0.1)最近已近发布了,但是在Google之外,它仍然非常不稳定。Dart是值得我们关注的语言,但是现在还不是一个明智的选择(not a real option yet )。
Opa
Opa是刚刚在8月份(2012年,译者注)拼凑出1.0发行版的新孩子。它是一种有一个正在成长的社区的强类型语言。先写好Opa代码,然后编译为其他像JavaScript,但并不只是客户端的语言。Opa把客户端和服务器端编程混合成为一个单独的文件。
Opa支持用一种语言开发客户端,服务器端和数据库。使用相同的代码基底(code base)。Opa最近还增加了对像MongoDB这类的非关系型数据库的支持。
不像Dart,Opa很大程度上借鉴/利用了像Erlang这样的函数式编程语言。这使得它很吸引书呆子,但是入门门槛相当的高。Opa缺乏像CoffeeScript这样的简单语法,你基本上不能在没有其他编程语言基础的条件下自己学会Opa。
尽管门槛高,但是你的学习投资的回报是只需要单独的开发环境,而不再需要在客户端和服务器端频繁切换语言。Opa还没有取得超越样本和小网站的大进步,但是它正在进步(It hasn’t grown much beyond samples and small websites, but it’s gaining ground)。
我应该做什么?
译注:这部分
The JavaScript problem is everyone’s problem; there are no good answers. It’s possible to write good JavaScript that scales to large projects, but that takes constant attention and the right culture.
There are a few other options for generating JavaScript (for example, Clojurecompiles into JavaScript), but they’re still small projects without much real-world use.
Google writes most of their client-side code with the Closure tools and they’re starting to adopt more Dart. Other large websites like Twitter use JavaScript combined with other technologies like Ruby On Rails. Big open source projects like WordPress mostly stick with straight JavaScript and jQuery. Facebook uses a combination of all of them. Microsoft combines jQuery with .Net and some other server-side technologies which interact with JavaScript. They’ve also released a new static-typed JavaScript variant called TypeScript.
That just scratches the surface. The CoffeeScript project maintains a comprehensive list of languages that compile into JavaScript.
If your project is small, then just write JavaScript. jQuery is very well done; so are many other JavaScript libraries. Keep your project small and the problems stay small.
But the line between small and large is blurry. Small projects get bigger with time, and you can get into big trouble writing large JavaScript applications without a lot of process to keep you out of the bad parts. The other options are either has-beens or aren’t-yets.
A big part of this problem is the difficulty of finding a single language that keeps everyone happy. Small websites want something simple that makes it easy to get started and produce an app quickly. Large projects want the structure to keep the code base maintainable for years. The two goals are at odds and no language has ever satisfied both parties. That’s why Visual Basic and C++ are both so popular.
There’s also no reason to choose just one. GWT combines well with regular JavaScript, and you can use the Closure Compiler simple optimizations with any JavaScript project.
JavaScript will never be the best language for all applications, but browsers won’t support another one anytime soon. The key to using JavaScript well is to understand its limitations and know when not to use it. JavaScript is easy for small projects; you need planning, care and help from other libraries to work on larger ones.
作者介绍:
Zack Grossbart is an engineer, designer, and author. He's a founding member of the Spiffy UI project, the architect of the WordPress Editorial Calendar, and an Architecting Engineer and Human Factors Specialist with NetIQ. Zack began loading DOS from a floppy disk when he was five years old. He first worked professionally with computers when he was 15 and started his first software company when he was 16. Zack lives in Cambridge, Massachusetts with his wife and daughter.