推荐序3

一个程序员到底需要掌握编程语言的多少特性?

每个程序员每天都在跟编程语言打交道,但是很少有人愿意真正了解这些“老朋友”。有一些编程语言的行为非常反直觉,比如JavaScript中著名的“0.1+0.2 ≠ 0.3”的现象。它看似语言的bug,但实际上来自浮点数的精度问题。正因如此,任何计算机语言的浮点类型都有着相似的问题。

而有些语言特性其实根本就是设计失误,尤其是对于一门只花了两个星期来设计的语言来说。比如JavaScript中的双等号,它“践踏”着一切的直觉,如“==”的传递性:

又如if(x)与if(x==true)的等价性:

所以我相信很少有程序员想要了解“双等号两边数据类型不一样的时候”的转换规则到底是什么。还有一些语言特性很有必要但是非常罕见,比如在最新的JavaScript标准中加入了code point系列API,用来处理Unicode基本平面(BMP)之外的字符。尽管在我十年的职业生涯里,一次都没有遇到过BMP之外的字符,然而这并不意味着它们不重要。

在你不知道的角落,一些你不知道的特性在被你用不知道的方式使用着。以前我在参与es-discuss邮件组讨论时,曾经非常冒昧地建议“函数调用与其后括号间不得加入换行规则”(即no line terminator规则)。但是很快收到回复,这样做会破坏一些既有代码,比如有一些奇思妙想的框架用下面的方式生成HTML:

这让我意识到,语言设计需要考虑的情况是极端和复杂的,一些特性对某些人来说无关紧要,但对另一些人来说是生命线。

今天,很多语言特性决定了技术产品的走向,比如Vue 3.0,它非常依赖Proxy特性。比起getter和setter实现的Vue 2.0,它对模型的侵入性更低,边缘case也更少。而从历史来看,在过去的几十年里,多数开发者只需要掌握他们关心的一部分特性就可以了,甚至可以躲在框架之上进行开发。

现在情况正在发生变化。在TC39,一些将会陪伴你职业生涯数十年的新特性,正在被针锋相对地讨论,而支持或者反对它们的理由可能与你不太相关—你必须从整体上理解语言的设计,才有参与其中的可能。即使多数程序员不需要参与这样的讨论,如今语言的更新速度也对程序员的素质提出了更高的要求,从ES5到ES2018,语言标准的表述篇幅增加到原来的三倍,这样的信息增长速度堪称恐怖。

所以,今天,编程语言学习的门槛客观上提高了,唯有站在更高的视角,跳出语言本身的约束,才能更好地应对莫测的未来。

我们讨论或者解释JavaScript的问题时,大多会引用标准的描述,比如执行上下文、变量环境、词法环境等,但是这些概念始终在变化。然而若我们以结构化程序设计的角度去看,不论是原有的函数级、全局作用域,还是新加入的模块、let级别的作用域,都没有跳出一般的结构化的思路。所以说,底层不等于本质,我们从更通用的角度去看待JavaScript,就会更容易理解它。尤其是,JavaScript是追求实用性的语言,它并没有试图像Haskell、Rust那样从语言角度做本质创新。

在我和我周围,很多前端工程师认识周爱民老师都是从他在2007年左右发布的系列博文“JavaScript面向对象编程”开始的。从那时候起,周老师对语言的研究就总是早于这些特性的大规模应用。作为架构师,周老师的思路总是能够给我们前端带来一些新的灵感。在这一次的改版中,周老师又为图书加入了不少新内容(比如关于并行特性的部分),我很期待这些新内容在未来成为每个前端程序员的新武器。

程劭非(winter)

2020年01月