为啥 <object> 的类型是函数?

Posted

技术标签:

【中文标题】为啥 <object> 的类型是函数?【英文标题】:Why type of <object> is a function?为什么 <object> 的类型是函数? 【发布时间】:2016-10-06 01:22:03 【问题描述】:

当我使用 chrome devtools 时,我对此感到很奇怪。 但似乎 typeof &lt;object&gt; 是一个“函数”。 我没有找到任何解释或参考。

这是一个简单的例子:https://jsfiddle.net/fez34zbf/ html

<object></object>
<video></video>

JS:

console.log(typeof document.querySelector('object'));
console.log(typeof document.querySelector('video'));

控制台结果将是:

function 
object

有什么想法吗?

【问题讨论】:

我认为问题是,HTMLObjectElement 实例是什么类型的函数? 以前有人问过这个问题:***.com/questions/13873684/…,但 Till 的回答似乎更广泛。 【参考方案1】:

如前所述,typeof 必须为所有具有[[Call]] 内部方法的对象返回"function"。(spec)。所以有趣的部分是HTMLObjectElement 的实例出于某种原因有一个[[Call]] 内部方法。

firefox 和 chrome 都有错误报告。虽然 chrome 问题上的 firefox 问题没有回复,但有一个解释是 [[Call]] 被添加到 HTMLObjectElement

是的,没错。 SetCallAsFunctionHandler() 使对象可以根据 EcmaScript 调用,因此我们必须为 typeof 返回“函数”。

SetCallAsFunctionHandler 似乎是 v8 中的一些实现细节。根据问题 chrome used to report object as the typeof instances of HTMLObjectElement 但他们将其更改为与 firefox 兼容。


现在为什么HTMLObjectElement 上有一个[[Call]] 内部方法?正如this *** answer 所暗示的,这似乎被某些插件使用。 HTMLObjectElement 被插件(例如 flash)使用。其中一些插件可能除了使用此功能的输入。

查看铬的sourcecode,似乎有一些代码确实可以处理一些遗留回调(V8HTMLEmbedElement.cppV8HTMLPlugInElementCustom.cpp)。

在thisfirefox 票证中也确认了这一点

为什么 Embed/Object 元素首先是可调用的? [...] 据任何人所知,因为某些插件会在您调用它们时执行某些操作,并且出于兼容性原因没有人愿意破坏它...

我没有找到任何定义此行为的规范。 html5 规范提到了 legacy caller operation,但没有明确定义它是如何工作的

总结一下:typeof document.createElement('object')"function",因为它有一个[[Call]] 内部方法。由于遗留原因,它有一个[[Call]] 内部方法。


如果你在 chrome 中执行这段代码

(function()
  'use strict';
  return document.createElement('object')()
)()

你得到undefined 作为返回值。如果你在 Firefox 中执行它,你会得到一个异常

组件不可用" nsresult: "0x80040111 (NS_ERROR_NOT_AVAILABLE)" 位置: "JS frame :: 调试器评估代码 :: :: line 1" 数据: 否

有趣的是document.createElement('object') instanceof Functionfalse,因此Function.prototype 中的任何方法都不存在于HTMLObjectElement

【讨论】:

很好的深入回答【参考方案2】:

如https://es5.github.io/x11.html#x11.4.3 中所述,HTMLObjectElement(HTMLEmbedElement 也是如此)具有[[Call]] 内部属性。 typeof 检查此属性以返回 "function",我同意这首先是相当令人惊讶的。

【讨论】:

为什么它有[[Call]]属性?

以上是关于为啥 <object> 的类型是函数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥首选 Java 类的接口?

Java中的Class类的newinstance方法返回值为啥是object类型的?

为啥 c++11 中的 lambda 函数没有 f​​unction<> 类型?

JavaScript为啥(typeof Object)返回的是function

JavaScript基础 null:object 类型,转成bool类型是 :false Boolean()系统函数

c++中重载输出操作符,为啥要返回引用