如何确保ES3程序在ES5引擎中运行?

use*_*621 5 javascript backwards-compatibility ecma262 ecmascript-5

所以ECMAScript 5引入了与ECMAScript 3的一些不兼容性.


示例:

已经写了许多文章,说明在ES5严格模式下this === null || this === undefined是可行的:

"use strict";
(function () {
    alert(this); // null
}).call(null);
Run Code Online (Sandbox Code Playgroud)

但是,标准 真正建议的是ES5引擎在非严格模式下也允许这样:

15.3.4.3 ...将thisArg值作为this值传递而不进行修改.这是对第3版的更改,其中a undefinednullthisArg替换为全局对象,ToObject应用于所有其他值,并将结果作为this值传递.

目前,IE9是唯一以这种方式实际实现ES5的浏览器,事实证明这可能会破坏当前的脚本.大.


ES5规范的 Annix E 列出了许多其他不兼容性.

那么,确保我们久经考验的ES3脚本能够完美运行的最佳方法是什么?某种自动化测试套件?我们必须手动测试吗?

All*_*ock 6

对于记录,提问者对ES5 15.3.4.3的解释是不正确的.在ES5中对非严格函数的任何调用都应该与ES3中的相同.全局对象仍然传递给任何非严格函数,该函数使用null或undefined作为此值调用.

缺少的分析是10.4.3"输入功能代码":

当控件进入函数对象F中包含的函数代码的执行上下文,调用者提供thisArg和调用者提供的argumentsList时,执行以下步骤:

  1. 如果函数代码是严格代码,请将ThisBinding设置为thisArg.
  2. 否则,如果thisArgnull未定义,则将ThisBinding设置为全局对象.
  3. ...

ES3指定调用者负责将全局对象替换为null或未定义此值.ES5指定被调用者具有该责任(如果它不是严格模式函数).对于非严格的代码,这不是可观察到的差异.当被调用者是严格函数时,规范更改只会产生差异.


kan*_*gax 4

自动化测试套件当然是一个好主意。

\n\n

由于现在越来越多的实现实现了 ES5,因此在较新的浏览器中运行脚本/库/应用程序的测试套件是确保兼容性的好方法。

\n\n

我有一个ES5 兼容性表,列出了一些更流行的实现的支持级别。它并不详尽,但它显示了总体方向 \xe2\x80\x94 最新的 IE、WebKit、Chrome 和 Firefox 都具有相当好的 ES5 支持。对于完整的一致性测试,您始终可以运行官方 ES5 测试套件(为了方便起见,我在网上提供了该套件

\n\n

如果没有测试套件(应该确实存在,因为由于其他原因它非常有用),您可以在较新的(符合 ES5 的)实现之一中运行脚本/库/应用程序,然后查看哪些有效以及哪些有效失败。

\n\n

另一种方法是查阅附录 E。请注意,尽管该列表看起来相当大,但它并不像看起来那么糟糕。ES5 的目标之一是让 ES3 的过渡或多或少变得轻松,将更彻底的变化转移到选择严格模式的领域。

\n\n

该列表中的许多兼容性更改可能会被忽视。以 15.1.1 中的更改为例,其中 global undefinedNaNInfinity现在是只读的。考虑到正常的应用程序不会重新分配这些全局属性 \xe2\x80\x94 ,除非错误\xe2\x80\x94 ,此更改更像是一个令人愉快的“错误捕获器”而不是“应用程序破坏者”。

\n\n

另一个看似无害的更改是在 15.10.2.12 中,其中空白字符类 ( \\s) 现在也匹配 <BOM> ( U+FEFF) 字符。考虑到当前实现中的所有偏差(即使是 ES3),这种变化在大多数应用程序中可能不会被注意到。

\n\n

然而,还有更危险的变化,例如parseInt它不再将以 0 开头的字符串视为八进制值。parseInt(\'010\')不应8再产生(尽管某些实现选择故意违反该行为)。尽管如此,依靠parseInt没有第二个“基数”参数从来都不是一个好的做法。因此,如果您的应用程序始终指定基数,则无需担心。

\n\n

因此,请参阅附件 E,在较新的实现(最好是多个实现)中测试您的脚本,并遵循最佳实践。这是确保兼容性的好方法。

\n