15

假设您将获得一堆 .js 文件,现在您的工作是将它们分类为如下组:

  • 至少需要 JavaScript 1.85
  • 至少需要 E4X (ECMAScript 4 EX)
  • 至少需要 ECMAScript 5

或类似的东西。

我对任何解决方案都感兴趣,尤其是那些使用 JavaScript 或 PHP 的解决方案。这用于创建自动化规范,但这无关紧要 - 这是一个很好的任务,应该很容易解决 - 但是,我不知道如何,这对我来说并不容易。所以,如果这对你来说很容易,请分享任何提示。

我希望这样的东西 - http://kangax.github.com/es5-compat-table/# - 只是不适用于浏览器,而是要针对不同的 JavaScript 实现检查给定文件。

我的猜测是,每个版本都必须有一些可以测试的细节。但是,我只能找到有关“此浏览器支持什么版本”的内容。


PS:不要从字面上理解“现在是你的工作”,我用它来演示任务,而不是暗示我希望为我完成工作;在解决这个问题的过程中,如果能得到一些帮助或指导就好了。


编辑:我采取了简单的方法,要求 ECMAScript 5 至少得到当前 FireFox 的支持,以便我的项目能够按预期和预期工作。

但是,我仍然对任何解决方案尝试感兴趣,或者至少对“可能(使用 XY)”或“不可能,因为......”的明确答案感兴趣;XY 可以只是一些关键字,例如 FrameworkXY 或 DesignPatternXY 或其他任何内容,当然也可以是更详细的解决方案。

4

2 回答 2

3

本质上,您正在寻找某些 javascript 文件的最低要求。我会说这在运行时是不可能的。JavaScript 是一种动态语言。因此,您没有编译时错误。结果,直到您在某个封闭范围内,您才能知道某些东西不起作用,即使那样它也会产生误导。您的依赖项实际上可以解决许多兼容性问题。

例子:

  • JS 文件 A 使用了一些 ES5 特性
  • JS 文件 B 为缺乏 ES5 的浏览器提供了一个 shim,或者至少以某种方式模仿了它。
  • JS 文件 A 和 B 总是一起加载,但单独 A 看起来不起作用。

示例 2:

  • Object.create 是您要测试的内容
  • 一些名叫 Crockford 的人将 create 添加到 Object.prototype
  • Object.create 现在可以在不太兼容的浏览器中工作,并且没有任何问题。

解决方案1:

  1. 构建或查找依赖关系图。您肯定已经有一个依赖映射,或者显式地或者您可以通过迭代 HTML 文件来生成它。
  2. 在功能减少的环境中运行所有相关的代码路径(例如:ES5,然后是 E4X,然后是 JS 1.x,等等)。
  3. 一旦 JS 文件包因某些代码路径失败,您就会知道它们的最低要求。
  4. 也许您可以遍历对象中的公共函数并使用依赖注入来填充构造函数和方法。不过这听起来真的很难。

解决方案2:

  1. 使用webdriver在各种环境中访问您的页面。
  2. 映射window.onerror到一个函数,该函数告诉您当前页面是否在执行某些操作时损坏。
  3. 出错时,您将知道当前页面上的捆绑包存在问题,因此请保存该数据。

这两种解决方案都假定您始终编写完美的 JS,永远不会出错,这是您应该努力的,但不现实。这有可能; 但是,为您提供一些基本的“冒烟测试”。

于 2013-03-18T22:59:54.403 回答
2

这不可能以确切的方式进行,而且对于此类问题,这也不是看待事物的好方法。

为什么它不可能

Javascript 没有静态类型。但是属性是由原型链决定的。这意味着对于任何一段代码,在确定函数调用将调用哪个函数之前,您都必须推断出对象的类型并检查原型链。

例如,您必须能够判断$(x).bind()o$(x).map不是在调用 ecmascript5mapbind函数,而是调用 jQuery 函数。这意味着您确实必须解析整个代码并推断类型。如果您没有完整的代码库,这是不可能的。如果您有一个接受对象的函数并调用了 bind,您将不知道这是否应该是,Function.prototype.bind或者jQuery.bind因为直到运行时才决定。事实上,它可能(尽管不是良好的编码实践)两者兼而有之,并且运行的内容取决于函数的输入,甚至取决于用户输入。因此,您可能可以对此进行猜测,但不能完全做到。

让这一切变得更加不可能的是,eval 函数与获取用户输入或 ajax 数据的能力相结合,这意味着您甚至不知道某些对象是什么类型或可能是什么类型,甚至抛开 eval 可能尝试运行的问题符合任何规范的代码。

这是一段您无法解析的代码示例

var userInput = $("#input").val();

var objectThatCouldBeAnything = eval(userInput);

object.map(function(x){
   return !!x; 
});

无法判断此代码​​是在 eval 中解析 jQuery 对象并运行,jQuery.map还是生成数组并运行Array.prototype.map。这就是像 javascript 这样的动态类型语言的优点和缺点。它提供了极大的灵活性,但限制了您在运行时之前对代码的了解。

为什么它不是一个好策略

ECMAScript 规范是一个标准,但在实践中它们从未完美或一致地实施。不同的环境实现标准的不同部分。拥有一段“ECMAScript5”代码并不能保证任何特定的浏览器都能完美地实现其所有属性。您确实必须逐个属性地确定这一点。

你最好做的是找到代码使用的函数或属性的列表。然后,您可以将其与特定环境支持的属性进行比较。

由于上述原因,这仍然是一个难以解决的问题,但它至少是一个有用的问题。即使使用松散的近似值,您也可以获得价值(假设bind实际上是 ecmascript5,除非它在$()包装上。那不会是完美的,但仍然可能有用)。

试图找出一个已实施的标准对于帮助您决定是否在特定环境中使用它是不切实际的。最好知道它使用了哪些函数或属性,以便您可以将其与环境进行比较,并在必要时添加 polyfill。

于 2013-03-24T23:50:32.030 回答