如何确保ES3程序能够在ES5引擎中运行?
因此,ECMAScript 5 引入了与 ECMAScript 3 的一些不兼容性。
示例:
许多 文章已写明 这 === 空 || this === undefined
是可能的在 ES5 严格模式:
"use strict";
(function () {
alert(this); // null
}).call(null);
但是,标准真正表明ES5引擎也允许在非严格模式:
15.3.4.3 ... thisArg 值不加修改地作为
this
值传递。这是对第 3 版的更改,其中undefined
或null
thisArg 被替换为全局对象,并且 ToObject 应用于所有其他值,并且该结果作为 <代码>此值。
目前,IE9 是唯一真正以这种方式实现 ES5 的浏览器,事实证明这可能 中断当前脚本。伟大的。
ES5 规范 的 Annix E 列出了许多其他不兼容性。
那么,确保我们久经考验的 ES3 脚本能够继续完美运行的最佳方法是什么?某种自动化测试套件?我们必须手动测试这一切吗?
So ECMAScript 5 introduces some incompatibilities with ECMAScript 3.
Example:
Many articles have been written stating that this === null || this === undefined
is possible in ES5 strict mode:
"use strict";
(function () {
alert(this); // null
}).call(null);
But, what the standard really suggests is that ES5 engines also allow this in non-strict mode:
15.3.4.3
...
The thisArg value is passed without modification as thethis
value. This is a change from Edition 3, where aundefined
ornull
thisArg is replaced with the global object and ToObject is applied to all other values and that result is passed as thethis
value.
Currently, IE9 is the only browser that actually implements ES5 this way, and it turns out that this may break current scripts. Great.
Annix E of ES5 spec lists dozens of other incompatibilities.
So what's the best way to make sure that our well-tried ES3 scripts will continue running flawlessly? Some kind of automated test-suite? Will we have to test it all manually?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据记录,提问者对 ES5 15.3.4.3 的解释是不正确的。 ES5 中对非严格函数的任何调用都应该与 ES3 中的明显相同。全局对象仍会传递到任何使用 null 或 undefined 作为 this 值调用的非严格函数。
分析中缺少的部分是 10.4.3“输入功能代码”:
ES3 指定调用者负责用全局对象替换 null 或未定义的 this 值。 ES5 指定被调用者具有该责任(如果它不是严格模式函数)。对于非严格代码,这不是可观察到的差异。仅当被调用者是严格函数时,规范更改才会产生影响。
For the record, the questioner's interpretation of ES5 15.3.4.3 is incorrect. Any call to a non-strict function in ES5 should be observably the same as in ES3. The global object is still passed into any non-strict function that is called with null or undefined as the this value.
The missing piece of the analysis is 10.4.3 "Entering Function Code":
ES3 specified that the caller was responsible for substituting the global object for a null or undefined this value. ES5 specifies that the callee has that responsiblity (if it isn't a strict mode function). For non-strict code this is not an observable difference. The specification change only makes a difference when the callee is a strict function.
自动化测试套件当然是一个好主意。
由于现在越来越多的实现实现了 ES5,因此在较新的浏览器中运行脚本/库/应用程序的测试套件是确保兼容性的好方法。
我有一个 ES5 兼容性表,列出了一些更流行的实现的支持级别。它并不详尽,但它显示了总体方向——最新的 IE、WebKit、Chrome 和 Firefox 都有相当好的 ES5 支持。对于完整的一致性测试,您始终可以运行官方 ES5 测试套件(为了方便起见,我在网上提供了该套件就在这里< /a>)。
如果没有测试套件(应该确实存在,因为由于其他原因它非常有用),您可以在较新的(符合 ES5 的)实现之一中运行脚本/库/应用程序,然后查看哪些有效,哪些失败。
咨询附件E是另一种方法。请注意,尽管该列表看起来相当大,但它并不像看起来那么糟糕。 ES5 的目标之一是让 ES3 的过渡或多或少变得轻松,将更彻底的变化转移到选择严格模式领域。
该列表中的许多兼容性更改可能会被忽视。以 15.1.1 中的更改为例,其中全局
undefined
、NaN
和Infinity
现在是只读的。考虑到正常的应用程序不会重新分配这些全局属性 - 除了错误 - 这种变化更像是一个令人愉快的“错误捕捉器”而不是“应用程序破坏者”。另一个看似无害的更改是在 15.10.2.12 中,其中空白字符类 (匹配。 (
\s
) 现在也与U+FEFF
) 字符。考虑到当前实现中的所有偏差(即使对于 ES3),这种变化很可能不会被注意到在大多数应用中。但是,还有更危险的更改,例如
parseInt
中的更改以及它不再将以 0 开头的字符串视为八进制值。parseInt('010')
不应再生成8
(尽管某些实现选择 故意违反该行为)。尽管如此,依赖于没有第二个“基数”参数的parseInt
从来都不是一个好的做法。因此,如果您的应用程序始终指定基数,则无需担心。因此,请参阅附件 E,在较新的实现(最好是多个实现)中测试您的脚本,并遵循最佳实践。这是确保兼容性的好方法。
Automated test suite is certainly a good idea.
Since more and more implementations implement ES5 now, running the test suite for your script/library/application in newer browsers is a good way to ensure compatibility.
I have an ES5 compatibility table, listing level of support of some of the more popular implementations. Its not exhaustive, but it shows overall direction — that latest IE, WebKit, Chrome and Firefox all have quite good ES5 support. For a complete conformance test, you can always run official ES5 test suite (which I have online for convenience right here).
If there's no test suite (which should really exist, as it is very useful for few other reasons), you can just run script/library/application in one of the newer (ES5 conforming) implementations and see what works and what fails.
Consulting Annex E is another way to go. Note that even though the list seems quite large, it's not as bad as it seems. One of the goals of ES5 was to make transition from ES3 more or less painless, moving more radical changes into the realm of opt-in strict mode.
Many compatibility changes from that list are likely to go unnoticed. Take for example, change in 15.1.1, where global
undefined
,NaN
andInfinity
are now read-only. Considering that sane applications do not reassign these global properties — except by mistake — this change is more of a pleasant "error-catcher" rather than "app-breaker".Another liekly innocent change is in 15.10.2.12, where whitespace character class (
\s
) now also matches <BOM> (U+FEFF
) character. Considering all the deviations in current implementations (even in regards to ES3), this change is likely to go unnoticed in majority of applications.However, there are also more dangerous changes, such as that in
parseInt
and how it no longer treats strings beginning with 0 as octal values.parseInt('010')
should not produce8
anymore (although some implementations chose to deliberately violate that behavior). And still, relying onparseInt
without second "radix" argument was never a good practice. So if your application always specifies radix, there's nothing to worry about.So consult Annex E, test your script in newer implementations (preferably, multiple ones), and follow best practices. That's a good way to ensure compatibility.