是否有一种与环境无关的方法来检测Javascript主机对象?

Ste*_*las 8 javascript cross-platform ecma262 javascript-objects

我正在写一个Javascript stacktrace库.库需要检测程序员创建的特定对象或函数,还是作为环境的一部分(包括内置对象).主机对象由于其不可预测的行为而变得有点问题,因此我采用环境无关的方式来确定Javascript中的特定对象是否是主机对象(请参阅ECMAScript 3 - 4.3.8).但是,区分主机对象与本机对象和原始值对于其他项目中的程序员很有用,特别是在无浏览器的环境中,所以我想关注它,而不是主机对象在我的库中导致的问题或区分程序员创建的对象.

到目前为止,我只能提出依赖于运行javascript代码的环境的解决方案.例如:

// IE Only: does not implement valueOf() in Host Objects
var isHost = (typeof obj === 'object' && typeof obj.valueOf === 'undefined');

// Firefox Only: Host objects have own constructor
var isHost = (obj.constructor && obj.hasOwnProperty('constructor'));
Run Code Online (Sandbox Code Playgroud)

我注意到jQuery自己的isPlainObject()方法也依赖于环境,而且逻辑相当复杂.

也许这是因为具有宿主对象的野兽的性质(因为它们的行为是由环境定义的),但我想进一步深入研究这是否可能并且想知道是否有人遇到过这个特定的问题之前并准备好了解决方案.

所以.有人知道一个简单的独立于平台的解决方案来测试主机对象吗?如果它在无浏览器环境(如Node或Rhino)中运行,那么它就更好了.

可能的方法(可能不起作用):

  • 测试主机对象的特性似乎是一个失败的原因,因为它们的行为没有规范,但是测试该对象是否是ES3规范的一部分可能是可能的.
  • 我已经尝试使用Object.prototype.toString()给定的非常具体的定义,但结果是不确定的,因为一些环境(即IE)选择为本机和主机对象返回相同的值.
  • 可以通过检查constructor通过原型链的对象的最终值是否真的来实现instanceof Function.

kan*_*gax 5

当你看到宿主对象定义 - "由宿主环境提供的对象来完成ECMAScript的执行环境." - 很明显,没有简单的方法来确定对象是主机还是本机.

与本机对象不同,主机对象以特定于实现的方式定义内部属性(例如[[Prototype]],[[Class]]等).那是因为规范允许他们这样做.但是,主机对象没有"必须"要求以特定于实现的方式实现内部行为; 这是一种"可能"类型的要求.所以我们不能依赖于此.这些对象可能会或可能不会"怪异".没有办法说出来.

过去几乎没有尝试检测宿主对象,但所有这些都明显依赖于某些环境的观察(MSHTML DOM就是其中之一) - 请记住,宿主对象没有任何独特的模式/特征来识别通过.Peter Michaux 在此记录了大部分推论(请参阅 "功能测试主机对象"部分).臭名昭着typeof ... == "unknown"来自MSHTML DOM及其基于ActiveX的主机对象.请注意,Peter主要在浏览器脚本的上下文中讨论主机对象,并将检查缩小为"这是一个主机方法吗?","这是一个主机集合对象"等.

在某些环境中,宿主对象不会继承Object.prototype(使其易于检查),或者具有某些抛出错误的属性(例如,IE中某些"接口"对象上的"原型"),甚至在访问时自己抛出错误.

看起来您可能只是检查对象是否是规范中定义的对象之一,如果不是,则将其视为主机.但这并不会真正有用; 它只会为你提供非内置的对象.其中一些非标准对象仍然可以是本机的(这意味着它们将实现规范中描述的通常语义).

您最好的选择是测试您的应用程序/脚本的特定行为,主机对象可能是敏感的.这始终是最安全的方式.你打算从对象上访问某些东西吗?从对象中删除内容?添加对象的东西?测试它.看看它是否有效.如果没有 - 你可能正在处理宿主对象.


Jos*_*ith 0

我相信宿主对象的本质意味着没有一种简单的、与环境无关的方法来检测它们。如果您好奇的话,请参阅有关 SO 的讨论以了解更多信息。

正如您所注意到的,jQuery 项目也尝试过检测宿主对象并遇到类似的麻烦。该错误页面上的讨论非常有说服力。