Javascript: 世纪机器语言?

在我写了「颠覆者的游戏 - 程序语言」和「elixir - 灵丹妙药?or 徒有其名?」后,就有同学就让我讲讲javascript。对于这门让人又爱又恨的语言,真要讲,我都不知道怎么开头了。套用『北京人在纽约』里的台词:「如果你爱TA,请让TA用Javascript,做为一个程序员,TA此生无忧;如果你恨TA,请让TA用Javascript,做为一个程序员,TA基本毁了」。

无所不在的javascript

说Javascript程序员此生无忧有很多理由,最大的理由就是:web无处不在,有web存在的地方,就有javascript存在的地方,所以javascript程序员是皇上的女儿不愁嫁。一个好的javascript程序员,他的痛苦是:这么多工作机会,到底哪个是Sandberg说的rocket ship? [1]

javascript在web frontend的统治地位是毋庸置疑的。不像backend那么多千奇百怪的选择,在frontend,二十年来大浪淘沙,有且只有一门能在任何浏览器中运行的语言:javascript。而自 prototypescript.aculo.us 开启了小团队的web2.0之旅后,javascript的生态圈呈爆炸性的繁荣。

web backend不必多说,nodejs已经火热了几年,早年的流行词LAMP [2] 都换成了MEAN [3] 这样的full stack js framework。这让很多前端工程师努努力就变成了全栈,一下子转扶摇而上,冲到了鄙视链的上层。

在mobile frontend上,cordova,ionic等html5 mobile app framework在不断努力让生活在WebView下的基于javascript的hybrid mobile app能够达到接近native app的表现。作为移动领域的头牌,apple对javascript也是又爱又恨 —— 爱其繁荣的生态圈,快速产品化的能力 [4],恨其一次编写到处运行的优势,无奈这股浪潮已经势不可当,于是在iOS 8里,apple终于在面对WebView也提供了早就在safari中提供的Nitro JIT engine。我倒不是说hybrid mobile app完全会取代native app,目前还不具备这个可能,但很多应用场景,hybrid app已经能够很好胜任。

桌面系统的领地,被node-webkit,atom-shell等一大票基于CEF [5] 的chrome衍生品也攻克了。CEF的理念很简单:每个app就是一个退化的chrome(可以简单认为把沙箱的限制取消了),跑开发者定制的html/css/javascript。由于chrome是跨平台的,所以这样的软件也跨平台,而且界面和web一样,可以无比丰富(也可无比贴近本地应用)。

硬件开发?有的是创业公司,比如tessel,看中了javascript在程序员群体的可达性,尝试提供基于javascript的SDK,来直接操纵硬件。也许有一天,FPGA的逻辑可以用javascript来描述。

设计拙劣的javascript

作为一门语言,javascript是一俊遮百丑的典范。随便试几例: [6]:

如果你的另一半如此捉摸不定,是不是很想抽丫一大耳光,转身离去?可惜这也就止于意淫 —— 谁让人家颜值太高,小性子坏脾气再多,你也得忍着,对么?

javascript是可能现代编程语言中设计周期最短的,据说Brendan Eich只有10天时间来设计它,基本思路是他自己的背景(函数式编程)和网景/Sun的背景(Java和面向对象编程)的大杂烩 [7]:

(1) C的基本语法

(2) Java的数据类型和内存管理

(3) Scheme的函数能力(函数是一等公民)

(4) Self的 prototype 的继承机制

和其它深思熟虑设计出来的语言(比如说clojure [8]),javascript就是一个灾难。而更大的灾难是:原本只是在浏览器里跑一跑,对DOM进行简单操作,响应DOM事件,让静止的网页能够和用户有更多交互性的一门表达能力并不很强的,从来没想过单个应用会超过上千行代码(所以javascript连最基本的module都没提供)的语言,慢慢地成了世间万物(web)的主宰!

javascript程序员的撕扯人生

这真是件撕扯的事情。一方面语言有不少弱点,另一方面你又需要用这种语言去完成越来越多的事情。

比如说让人又爱又恨的 this。有好几种不同的 scope 或者 context 会使用 this,在层层嵌套的函数里,多少人用起来战战兢兢?

还有基于prototype的继承,有多少人真正研究一下prototype的概念,以及这么处理继承和其他主流面向对象语言的异同?优劣?

我们知道在学习一门新的语言时,大家往往会进行比较严格的语言训练,否则想把代码写正确并且写漂亮很难。但javascript不同,似乎没有人特别认真对待它,很多前端工程师或者后端工程师几乎就是翻一两个教程,因项目需要,顺带着把自己的语言能力扩展到javascript,根本没有系统学习,所以 —— 不得不直面各种各样的惨淡人生。

要getting things right,你需要了解其good part,避免其缺陷或者容易跑偏的部分。

(这图寓意深刻啊~)

救星:compile to javascript

摆脱这种困境最直接的方法是静下心来好好学习javascript,取其精华,去其糟粕。遗憾的是,这并不如想象的那样简单。有人看到了其中的机会:既然javascript不可替换,那何不发明(利用)一门语言,将其编译成javascript呢?就像C语言被编译成机器指令,或者java被编译成byte code?

(准机器代码)

(web世界的准机器代码)

于是,compile to javascript的语言便如雨后春笋般涨了出来。它们大致可以分三类:

1) 新语言,取javascript的子集(good parts)。如asm.js [9],coffeescript。coffeescript用更好更简洁的语法撰写代码,编译出来的javascript比较优美。使用起来毫无压力,大爱 和其函数式编程的风格。

2) 新语言,在javascript语言基础上扩展。如typescript。javascript的超集。没用过。

3) 已有语言的子集,能编译出javascript的子集。如coffeescript,gopher2js。

点击「阅读原文」可以看到完整的compile to javascript的清单。

编译这事,并不简单,严复说译事三难:「信,达,雅」。这三点对应于编译就是:

1) 准确无误。不能歪曲了程序员的意思。

2) 不拘泥于原文,尽可能优化。在这里就是minify的能力要到位。

3) 编译结果越小越好。在这里就是dead code elimination。

你看一个标准的gcc编译器,这三点在不同的 -O 选项下,都能做到 [10]。而在compile to javascript领域里,做到(好) 2)与3)的很少。minify应该是编译时的动作,很多语言(比如coffeescript)都忽略它,而是使用各种现成的uglifier在编译后进行。少了AST [11] 层面的支持,很多minify的事情都做不了。

dead code elimination更是如此,一个jQuery的Lib你可能就用到了dom operation,那各种animation的代码就是dead code。90%以上的语言在这个领域毫无作为。

这里要专门赞一下clojurescript,这三者它都做得很好,而且很美。clojurescript在设计之初,就把google closure compiler作为其编译基础。google closure compiler在优化javascript时的疯狂,堪比gcc的 -O3。它在做到「信」的基础上,最大程度地压缩你的代码,不仅删除所有不在执行路径上的代码,还把你的函数各种inline。当然,这是有代价的:你需要满足特定的约束,写能让closure compiler优化的代码 —— 这几乎不是正常人干的事情。所以clojurescript就替你完成这件事:你用clojure(的子集)写代码,它帮你生成满足closure script约束的javascript。

在小型项目上,compile to javascript的优势并不明显,但项目越大,系统越复杂,这种优势就越明显。atom是coffeescript写的,lighttable是clojurescript写的。我相信,随着这些compile to javascript的项目本身的逐渐成熟,以及其生态圈的逐渐完善,越来越多的复杂系统,会不再使用手写的javascript,转而使用表达能力更强的语言。


1. If you’re offered a seat on a rocket ship, don’t ask what seat. Just get on.

2. linux, apache, mysql, php

3. mongodb, express, angular, nodejs

4. 意味着单位时间能产生更多的app

5. Chromium Embedded Framework

6. 更多可以参见阮一峰的javascript 10个设计缺陷:http://www.ruanyifeng.com/blog/2011/06/10_design_defects_in_javascript.html

7. 见阮一峰的Javascript诞生记:http://www.ruanyifeng.com/blog/2011/06/birth_of_javascript.html

8. 简直和javascript是两个极端

9. 这个有空单独撰文描述

10. 函数inline,指令优化,删除无调用函数等

11. Abstract Syntax Tree

原文发布于微信公众号 - 程序人生(programmer_life)

原文发表时间:2015-03-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java工会

科大讯飞人工智能方向的一次面试经历

2685
来自专栏牛客网

滴滴android实习面经

2810
来自专栏java一日一条

暴露程序猿身份的8个行为

职业原因:编程语言都有自己特定的语法,程序员在开发者都要遵守这些。当然,还有一些约定俗成的编程规范,如代码缩进(是缩进4个字符还是8个字符)、注释风格,采用骆驼...

891
来自专栏我和PYTHON有个约会

莱茨狗-Go语言第一弹-概述

那是2007年,那是各种编程语言百家争鸣烽火硝烟起的一年,谷歌公司针对软件开发出现的各种让人不爽的问题进行了整理,并由首席总教头Rob Pike主导让所有的名家...

702
来自专栏java一日一条

4个理由告诉你Java为何排行第一

Java已经有20年的历史了,甚至更久,而这取决于你所询问的人和你的计算方式。忽略它的年龄不看,Java依然排行第一。它的实用性、性能和向后兼容性都彰显其价值所...

872
来自专栏潇涧技术专栏

Interview of Alibaba

阿里实习的事情终于尘埃落定了,自己的坚持也算是有了一份答复,这个过程真的要感谢很多很多人,2015年注定是我遇见我的众多贵人的一年!

1343
来自专栏数据小魔方

leaflet在线地图之热力密度图

之前在练习leaflet的时候没有找到R语言leaflet中的热力密度图接口函数,一直感觉很遗憾。

1592
来自专栏程序人生

那些年,我追过的语言

程序君也年轻过,年轻的代价就是盲目追随。 从MS-DOS6.0开始,程序君就是微软的狂热拥趸。 这种狂热自win95走上高潮(有谁还记得win95光盘里带的Go...

3785
来自专栏带你撸出一手好代码

kotlin, 一种新的android平台一级开发语言

今天看到一则科技新闻, 大致内容是google将kotlin语言作为android应用开发的一级语言, 与java并驾齐驱, 这是一个开发界的大事件大新闻, 连...

3528
来自专栏顶级程序员

面试分享:一年经验初探阿里巴巴前端社招

一般阿里社招都是招3-5年的P6+高级工程师,当初自己一年经验也没有想过有这个面试机会。 虽然没想着换工作,但是经常关注一些招聘网站的信息,某一天,在某bos...

5567

扫码关注云+社区

领取腾讯云代金券