JavaScript 中 XMLHttpRequest 的类型是什么?

What is the type of XMLHttpRequest in JavaScript?

我想知道 XMLHttpRequest 对象在 JavaScript 中的标准类型是什么。根据引擎的不同,我发现了不同的结果。

在 Firefox 和 Chrome 中:

typeof XMLHttpRequest //=> "function"

在 Safari 中:

typeof XMLHttpRequest //=> "object"

W3C规范使用interface关键字来定义XMLHttpRequest,:

[Constructor(optional XMLHttpRequestOptions options)]
interface XMLHttpRequest : XMLHttpRequestEventTarget {
  // ...
}

MDN definition 指出:

XMLHttpRequest is a JavaScript object...

但是 Firefox returns "function",所以这个词至少是模糊的。该定义目前还规定:

It's now being standardized in the W3C.

我到处看了看,但没有明确的答案™。有没有?

除此之外,还有一些额外的背景知识


问题的背景

我刚刚修复了这段代码中的一个错误:

if (typeof XMLHttpRequest === "function") {
  // do something
}

该bug目前只出现在Safari 7中(其他版本未测试)。该代码在 Firefox 和 Chrome 中运行良好。修复是:

if (typeof XMLHttpRequest !== "undefined") {
  // do something
}

问题来自假设 typeof XMLHttpRequest 在任何地方都相同...

如果您只想检查 XMLHttpRequest 是否存在,那么您可以使用:

if (typeof XMLHttpRequest !== "undefined") {
  // do something
}

if (window.XMLHttpRequest !== undefined) {
  // do something
}

if (this.XMLHttpRequest !== undefined) {
  // do something
}

根据 ECMAScript 5 和 Web IDL 规范,Safari 在这里似乎是错误的。 typeof XMLHttpRequest 应该 return "function".

WebIDL spec says:

If the interface is declared with a [Constructor] extended attribute, then the interface object can be called as a function to create an object that implements that interface.

...

The internal [[Call]] method of the interface object behaves as follows...

与此同时,specification for typeof in the ESCAScript 5 spec 有一个 return 值 table,条目为:

Object (native or host and does implement [[Call]]) : "function"

Object (host and does not implement [[Call]]) : Implementation-defined except may not be "undefined", "boolean", "number", or "string".

从这个 table,我们可以看出任何实现 [[Call]] 的对象(本机或主机)都需要导致 typeof 产生 "function"。 WebIDL 规范要求 [Constructor] 接口对象来实现 [[Call]],因此它们应该产生 "function".