新时代新潮流WebOS 【16】作为浏览器方言的JavaScript
旧约-创世纪-第11章 1-9,(Genesis [11:1-9])
“1 那时,天下人的口音,言语,都是一样。2 他们往东边迁移的时候,在示拿地遇见一片平原,就住在那里。3 他们彼此商量说,来吧,我们要作砖,把砖烧透了。他们就拿砖当石头,又拿石漆当灰泥。4 他们说,来吧,我们要建造一座城和一座塔,塔顶通天,为要传扬我们的名,免得我们分散在全地上。5 耶和华降临,要看看世人所建造的城和塔。6 耶和华说,看哪,他们成为一样的人民,都是一样的言语,如今既作起这事来,以后他们所要作的事就没有不成就的了。7 我们下去,在那里变乱他们的口音,使他们的言语彼此不通。8 于是,耶和华使他们从那里分散在全地上。他们就停工,不造那城了。9 因为耶和华在那里变乱天下人的言语,使众人分散在全地上,所以那城名叫巴别(就是变乱的意思)。”
Douglas Crockford以创世纪通天塔的故事为导言,开始了他对JavaScript的辩护。关于通天塔的读解有多种,一种读解是,神在警告人类不要狂妄,学 会谦卑。另一种读解是,这段话解释了方言的起源,没有其它隐喻。Douglas把这段故事和计算机语言联系在一起,他说,
“程序的核心问题在于驾驭复杂 性。在应对复杂多变的需求时,如果一个程序语言不能有助于驾驭复杂系统,那么结果就是混淆不清,接踵而至的就是失败。”
几十年来,人们设计了形形色色的计算机 语言,为什么不设计一种广为接受的,一统天下的语言,这样人们就可以把精力集中到这种语言的普及教育,并且设计开发各种工具,使这个世界通用语言变得功能 更加强大,使用更加简便?Douglas说,“我们已经尝试过了,但是所有努力无一不以失败告终”。究其原因,当一个语言要处理的应用越来越多时,需要赋 予这种语言的功能也就越来越多,于是语言本身就越变越复杂,于是语言就越变越晦涩。
“所以,我们就看到大量的专门的语言出现。这些特殊语 种在应付特定范围的任务时,非常有效,这就足够了。当人们需要完成特定任务时,有合适的语言作为工具,这是天赐之福”。“语言设计的艺术在于知道如何取 舍。一个好的语言所拥有的诸多功能,能够和谐地互为补充共同工作。一个好的语言不仅能够帮助我们更好地理解问题,并且有益于找到解决方案的最佳表述方式。 ”
“一个好的语言的功能并不追求包罗万象,而是由有限的功能所组成。但是,哪些功能是有用的,哪些可以舍弃,却众说纷纭,没有统一意见。吸收哪些功能,让语言变得更加强大,这是永无休止的争论议题。并不是说功能不重要,问题在于我们不知道每个功能有多重要。”
这位Douglas Crockford是JavaScript最知名的捍卫者,同时设计了JSON,JSLint,JSMin等等与JavaScript相关的构件和辅助工 具。JavaScript的发明人Brendan Eich盛赞他是Lambda编程和JavaScript的精神领袖。Doug不仅学问精湛,而且文采飞扬。Doug对于语言有广泛的研究,其中特别热衷 于Blissymbol的推广。
二战时犹太人Charles Bliss逃难到了上海,在这期间他试图学习中文。一方面他认识到象形文字的优势,同时认为要记住数以万计的中文字,实在是一件难度很大的任务。于是,他 发明了几千个象形符号,以此为基础,通过组合这些基本的象形符号来表达复杂的概念。这就是Blissymbol的由来。Blissymbol不仅可以表达 任何复杂的思想,而且非常容易学,甚至“比学习自己的母语还要容易”。Doug热衷于Blissymbol,同时对中国也十分友好。
关于 JavaScript,Doug写到,“大多数程序语言死于晦涩。只有少数语言,能够从一个项目组或者一个公司的试验品,扩散出去,吸引追随者。只有极少 数能够成为真正重要的语言。一门语言能否变得重要,有两条途径。第一个途径是体现某些重要的编程思想,或者提供实践这些思想的平台。Smalltalk和 Scheme就是通过这个途径走向成功的范例。虽然使用这些语言的人并不多,但是众口一词的评价是,它们的设计充满睿智,即便这种设计并不迎合时尚。虽然 它们本身并没有吸引很多使用者,但是对于未来的语言设计却具有深远的影响。另一个使一门语言变得重要的途径,是因为拥有众多用户而变得重要。在程序员选择 编程语言时,需要考虑的因素很多。但是用什么语言来编写浏览器脚本却无需左顾右盼,因为,至少目前而言,浏览器能够接受的编程语言,别无选择,只有 JavaScript。”
这真是一段坦荡得让人吃惊的评论。JavaScript之所以重要,完全是源于它是众多浏览器唯一接受的语言。 换而言之,如果没有这样的垄断地位,JavaScript也许就不会拥有如此众多的用户,没有众多的用户,而且也没有新颖的编程思想作为灵 魂,JavaScript或许就不再是一门重要的语言。
Python,Ruby等等语言是否能够替代JavaScript的地位呢?从技术上讲,是完全可能的。为什么JavaScript会占据垄断地位呢? Doug的解释是这样的,与前面的论述一样,坦荡得令人佩服。
“为什么这样一个有着明显缺陷的语言,会成为Web唯一的编程语言呢?Brendan Eich在Netscape任职的时候,成功地让他那个婆婆妈妈的领导,认识到Navigator浏览器需要一个脚本语言,而且只有重新发明一门新语言才 能胜任浏览器脚本这个工作。于是,一门新语言就开始匆匆忙忙地设计,匆匆忙忙地实现,而且压根就没有考虑是否能够延用现有的其它语言,去担当浏览器脚本这 个工作。事后不久,微软的IE浏览器项目组急于争夺Netscape的市场份额,他们逆向复制了Netscape的语言,全盘照抄,泥沙俱下。其它浏览器 开发商也追随微软的做法,盲目紧跟。并没有什么标准强制浏览器必须实现JavaScript,但是JavaScript无意中成为各个主流浏览器的唯一的 通用的脚本语言。没有谁仔细深入地审视过这门语言本身,以及它所针对的问题范畴,也没有甄别它是否能够称职地解决这些问题,更谈不上设计是否完备。 Netscape仓促中捏合了这门语言,然后它被复制到其它浏览器中去。当我们回顾JavaScript产生的背景,以及它成为事实上的Web编程语言的 标准的整个过程,我们有理由相信这门语言一定糟糕透顶。”
“尽管JavaScript存在惊人的缺陷,当我们深入分析这门语言的时候,会 发现其实它的内核,具有非常优秀的品质。当我们剥去污秽的外壳,JavaScript的内里,是富于表现力的,功能强大的编程语言。这门语言被出色地应用 到很多Ajax函数库里,操控XML-DOM,支持Web页面的交互,提供应用服务的平台。Ajax之所以流行,是因为JavaScript不仅能够完成 任务,而且表现出色,令人惊讶。”
在Doug看来,JavaScript的精髓在哪里呢?在“JavaScript, the Good Parts” (published by O’Reilly) 这本书的第10章,Doug列举了三条,
- Functions as first class objects
作为一类对象,JavaScript的函数可以像数值或者字符串那样,被动态地创建,存储,传输以及返回(return)。Java的method不是一类 对象。一个Java method结束运算时,可以返回数值或者对象,但是无法返回另一个method。C的函数也不是一类对象,但是可以通过函数指针(function pointer)迂回达到类似功效,所以C的函数又被称为二类对象。 - Dynamic objects with prototypal inheritance
在大多数Object-Oriented语言里,既有class,又有object,class是object的抽象蓝图,规定了属性和函数。譬如你我他都 是人,但凡是人都有头脑和四肢,这就是属性,但凡是人都能做一些思考和运动,这就是函数。但是JavaScript取消了class,所以在 JavaScript的语汇里,不存在“人”这样抽象的class,JavaScript从不说“他是一个人”,而只是说“他与我很像”。
取消class的好处在于精简了语言的复杂性,但是麻烦在于套用设计定式(design pattern)时,JavaScript就显得比较笨拙。Doug的文章成功地说服了大家,并不是JavaScript语言本身在表述Design pattern时显得笨拙,而是我们大多数人更习惯于传统的OO语言,习惯于既有class也有object,而不习惯于没有class的情况。 - Object literals and array literals
JavaScript表述object和array的方式非常简练,同时这种表述方式使object和array的数据读取,编辑以及其它操作也干净利索。这种表述方式,直接促成了JSON数据传输格式的产生。
Doug 的三条分析都对,但是斗胆冒犯一句,似乎没有搔到痒处。正如前文中Doug坦率承认的那样,JavaScript的卖点是对于浏览器的操控功能,而不是语 言本身的巧妙。但是令人失望的是,Doug为JavaScript辩护的重心,在于区别JavaScript语言本身,与寄生于这个躯体之上的污秽的附属 物。他说到,
“JavaScript是一个令人惊叹的语言,但不是好得让人惊叹,而是糟糕得让人惊叹。这个令人惊叹的本质,成就了它的恶名。JavaScript与 DOM,尤其是DOM那些既可怕又可恶的APIs纠缠不清。人们不清楚JavaScript与DOM的分界在哪里,人们喋喋不休地谈论如何改进 JavaScript,但是这些改进本身,对于web开发而言,与事无补。这个语言肩负着太多太多功能,其中包括很多彼此难以和谐共存的,以及设计时就存 在先天缺陷的功能。这个语言太冗长,就像约瑟夫皇帝评论Mozart的音乐那样。”
所以,Doug辩论的目的,是要还JavaScript一个清白,找还清白的方式,是剥离寄生于JavaScript的内核的DOM操控,HTML事件处理等等,彼此难以和谐共存的,以及设计时就存在先天缺陷的那些功能。
问题是,即便我们有了一个脱离污秽的冰清玉洁的JavaScript,充其量,我们又多了一个比Python和Ruby更好的脚本语言。但是这不是我们所需要的,我们需要的是如何高效地操控浏览器,换句话说,我们需要的正是那些污秽的附属物,具体说来,
- 如何捕捉发生浏览器页面的事件,譬如鼠标移动,点击和输入等等,对应DOM-tree的哪一个节点。
- 如何修改编辑DOM-tree,尤其是多个节点或者子树的相关互动。
- 如何调用浏览器外部函数,以及如何让外部函数调用浏览器内部指令。
Brendan Eich当年游说Netscape的领导时说得对,当时没有哪一个现成的语言具有上述功能,与其扩充现有语言的功能,不如另行发明一个新的语言,这个新的语言就是JavaScript。
我们今天反思JavaScript的目的,并不是讨论这门语言好不好,如何改进。我们要大胆地问一句,究竟有没有必要存在这门语言,对于操控浏览器而言, 或许我们需要的是protocol,而不是language。如果说互联网浏览器的历史积淀很沉重,积重难返,那么对于手机浏览器而言,大可轻装上阵,不 必重蹈历史的覆辙。