3.1 版本化

原则上,语言的一个新版本是一个清理的机会,可以清理过时的特性或者改变特性的工作方式。这意味着新的代码在语言的旧的实现中无法工作,老的代码在新的实现中无法工作。每段代码都和特定的语言版本关联。针对两个不同语言版本写两种不同代码是很常见的。

首先,你可以使用一种“用所有还是什么都不用”的方式:如果一个代码库需要使用新的语言版本,就必须彻底升级。Python 在从 Python 2 升级到 Python 3 的时候就是这样的。这样的话有个问题,将已有的代码库一次性全部升级可能是做不到的,尤其是代码库很大的时候。而且,这种方式对于 web 来说是不可行的,因为总是有老代码,而且 JavaScript 引擎会自动升级。

第二,你可以让一个代码库包含在多个语言版本都可运行的代码,通过根据版本切换代码的方式。你可以通过一个专用的互联网媒体类型标记 ECMAScript 6 的代码。这样的媒体类型可以和一个 HTTP 头关联在一起:

Content-Type: application/ecmascript;version=6

也可以和 <script> 元素中的 type 属性关联在一起( type 默认值text/javascript ):

<script type="application/ecmascript;version=6">
    ···
</script>

这是在代码之外指定版本。另一种方案是在代码内指定版本。例如,将下面的代码放在 JavaScript 文件的第一行:

use version 6;

两种标记的方法都很容易产生问题:外部版本标记法很脆弱,容易丢失;内部版本标记法又会使代码显得杂乱。

一个更根本的问题是,针对不同的语言版本,要维护不同的执行引擎。这就引起了一些问题:

  • 引擎变得臃肿,因为要实现所有版本的语义。对于分析语言的工具也带来了同样的问题(比如类型检测, JSLint )。
  • 开发者需要记住版本之间的不同点。
  • 代码变得更加难以重构,因为在移动代码的时候需要考虑语言版本的问题。

因此,应该避免版本化,尤其是 JavaScript 和 web 。

3.1.1 非版本化的升级

但是我们如何解决版本化的问题?通过一直向后兼容。这意味着我们必须放弃一些野心,比如清理 JavaScript :我们不能引入破坏性改变。向后兼容意味着不要移除特性,也不要修改特性。原则是:“不要破坏 web ”。

然而,我们可以添加新的特性,并且使已有的特性更加强大。

因此,对于新的引擎不需要版本化管理了,因为仍然可以运行老的代码。 David Herman 称这种避免版本化的方法为一个 JavaScript ( One JavaScript(1JS) [1] ),因为它使 JavaScript 避免分成几种不同的版本或模式。正如我们将要看到的,由于严格模式,使得 1JS 甚至移除了一些已有的分裂。

一个 JavaScript ( One JavaScript )不是说你必须完全放弃语言清理。你可以引入新的干净的特性,而不是清理掉已有的特性。其中一个例子就是 let ,它声明了块级范围的变量,是 var 的一个升级版本。它并不取代 var ,而是作为高级可选项一直和 var 并存。

某一天,甚至可能清除掉没人使用的特性。一些 ES6 特性是在调查过 web 上的 JavaScript 代码才设计的。举两个例子:

  • let 声明很难添加到非严格模式,因为 let 在这种模式下是保留字。使用 let 关键字看起来像是合法 ES5 代码的形式是:

      let[x] = arr;
    

    经研究得出,在 web 上没人以这种方式在非严格模式下使用变量 let 。这使得 TC39 将 let 添加进了严格模式。在本章后面讲述了这是如何做的。

  • 函数声明确实偶尔会在非严格模式下的代码块中出现,这就是为什么 ES6 规范描述了 web 浏览器可以采用的措施来确保这样的代码不会被破坏。后面详细讲解。

下一章描述了我们刚才看到的反面:部署 ES6 ,以便能够在支持 ES6的引擎上运行,也能够在不支持的引擎上面运行。

results matching ""

    No results matching ""