简体   繁体   English

Javascript:typeof和instanceof结果是否矛盾?

[英]Javascript: typeof and instanceof results contradicting?

I am seeing contradicting results when doing typeof and instanceof on an object. 在对象上执行typeof和instanceof时,我看到了相互矛盾的结果。

I have the following test page: 我有以下测试页面:

<html>
    <body>
        <object id="test" />
        <script type="text/javascript">
            var foo = document.getElementById("test");
            console.log(typeof foo); // returns "function"
            console.log(foo instanceof Function); // returns false
            console.log(foo instanceof Object); // returns true
        </script>
    </body>
</html>

"typeof foo" is returning "function" but "foo instanceof Function" is returning false. “typeof foo”返回“function”但“foo instanceof Function”返回false。

This doesn't make sense to me. 这对我来说没有意义。 How can an object have a type be function but not be an instance of a function? 对象如何将类型设为函数但不是函数的实例? Also, I expected "typeof foo" to return "object". 另外,我希望“typeof foo”返回“对象”。

object and embed HTML elements are host objects. objectembed HTML元素是宿主对象。

ECMAScript3 11.4.3 didn't define what typeof should return for these. ECMAScript3 11.4.3没有定义应为这些返回的typeof The table of returned values for Objects was 对象的返回值表是

  • Object (native and doesn't implement [[Call]]): "object" 对象(本机的,不实现[[Call]]): "object"
  • Object (native and implements [[Call]]): "function" 对象(native和implements [[Call]]): "function"
  • Object (host): Implementation-dependent 对象(主机):依赖于实现

However, returning "function" is consistent with ECMAScript5 11.4.3 : 但是,返回"function"与ECMAScript5 11.4.3一致:

  • Object (native and does not implement [[Call]]): "object" 对象(本机的,不实现[[Call]]): "object"
  • Object (native or host and does implement [[Call]]): "function" 对象(本机或主机并实现[[Call]]): "function"
  • Object (host and does not implement [[Call]]): Implementation-defined except may not be "undefined" , "boolean" , "number" , or "string" . 对象(主机并没有实现[[Call]]):实现定义,但可能不是"undefined""boolean""number""string"

object and embed HTML elements are objects with an internal [[Call]] property, so typeof must return "function" . objectembed HTML元素是具有内部[[Call]]属性的对象,因此typeof必须返回"function"

This is explained in Bug 268945 : 错误268945中对此进行了解释:

  • Comment #15 , by Boris Zbarsky: 评论#15 ,作者:Boris Zbarsky:

    The [[Call]] is very intentional on the DOM side: these are callable objects. [[Call]]在DOM端是非常有意的:这些是​​可调用的对象。

  • Comment #16 , by Tom Schuster: 评论#16 ,汤姆舒斯特:

    This bug is invalid these object have a [[Call]] internal method and ES5 11.4.3 explicitly say "Object (native or _host_ and does implement [[Call]])" => "function". 这个bug无效,这些对象有[[Call]]内部方法,ES5 11.4.3明确说“Object(native或_host_并且实现[[Call]])”=>“function”。

Since object and embed HTML elements implement an internal [[Call]] property, they are callable objects . 由于objectembed HTML元素实现了内部[[Call]]属性,因此它们是可调用对象 However, they are not functions: 但是,它们不是功能:

4.3.24 function 4.3.24功能

member of the Object type that is an instance of the standard built-in Function constructor and that may be invoked as a subroutine Object类型的成员,它是标准内置Function构造Function一个实例,可以作为子例程调用

object HTML elements inherit from HTMLObjectElement.prototype , and embed HTML elements from HTMLEmbedElement.prototype . object HTML元素继承自HTMLObjectElement.prototype ,并embed来自HTMLEmbedElement.prototype HTML元素。

The prototype chain continues with 原型链继续

  • HTMLObjectElement.prototype
  • HTMLElement.prototype
  • Element.prototype
  • Node.prototype
  • Object.prototype

Therefore, they are not Function instances, because they don't inherit from Function.prototype . 因此,它们不是Function实例,因为它们不从Function.prototype继承。

The essential fact is that DOM elements (obtained, for example, using document.getElementById() ) are not native JavaScript objects. 基本的事实是DOM元素(例如,使用document.getElementById() )不是本机JavaScript对象。 Instead, they are host objects . 相反,它们是主机对象 As such, they are not subject to the usual rules that apply to native JavaScript objects, and their behaviour will (quite legitimately) vary wildly from one browser to the next. 因此,它们不受适用于本机JavaScript对象的通常规则的约束,并且它们的行为将(非常合理地)从一个浏览器到下一个浏览器变化很大。

In short, all bets are off. 简而言之,所有的赌注都没有了。 Don't rely on the behaviour of host objects outside of their documented API. 不要依赖于其记录的API之外的宿主对象的行为。

Related references: 相关参考:

Safari returns ' function ' for typeof document.getElementsByTagName('p') , Safari为typeof document.getElementsByTagName('p')返回' function ',

which gave me a bad time a while ago, when I assumed all clients would return 'object'. 这让我很久以前的一段时间,当我假设所有客户都会返回“对象”时。

It is good to test our pre-conceptions, even when an exception makes no sence. 测试我们的前概念是很好的,即使异常没有发生。

Also, debuggers are lovely, but they do not always report the same values as their browser. 此外,调试器很可爱,但它们并不总是报告与浏览器相同的值。

In your first example this dom element does not exist when the script is run. 在第一个示例中,运行脚本时不存在此dom元素。 In your second it does, the answers are correct in the second the difference is between typeof and constructor. 在你的第二个,它的答案是正确的,第二个是typeof和constructor之间的区别。 typeof returns a function because document.getElementById returns a function. typeof返回一个函数,因为document.getElementById返回一个函数。 constructor tells you the name of that function "HTMLElement". 构造函数告诉您该函数“HT​​MLElement”的名称。

you could for example invent your own elements starting with var myElement = new HTMLElement() 例如,您可以使用var myElement = new HTMLElement()开始创建自己的元素

I'm not sure why 'function' is returned for a <object> node, but the reason instaceof Function fails is because that's essentially a check against the constructor, the difference of which can be illustrated like so 我不确定为什么为<object>节点返回'function',但是instaceof Function失败的原因是因为它本质上是对构造函数的检查,其区别可以如此说明

<html>
    <body>
        <object id="test" />
        <script type="text/javascript">

            var foo = document.getElementById("test");

            var bar = function() {}

            console.log( typeof foo );
            console.log( foo instanceof Function );
            console.log( foo.constructor ); // Object()

            console.log( typeof bar );
            console.log( bar instanceof Function );
            console.log( bar.constructor ); // Function()

        </script>
    </body>
</html>

So in this case, it's actually typeof that is behaving oddly, and not in a way that is documented that I can see. 所以在这种情况下,它实际上typeof是奇怪的行为,而不是在一个方式是记录 ,我可以看到。

I found some additional strange behavior. 我发现了一些额外的奇怪行为。

If you move the javascript code above the object, then typeof works correctly but instanceof does not work. 如果您将javascript代码移动到对象上方,则typeof正常工作但instanceof不起作用。

<html>
<body>
    <script type="text/javascript">
        var foo = document.getElementById("test");
        console.log(typeof foo); // returns object (this is correct now)
        console.log(foo instanceof Function); // returns false (this is correct)
        console.log(foo instanceof Object); // returns false (this is wrong)
        console.log(foo instanceof HTMLElement); // returns false (this is wrong)
        console.log(foo instanceof Node); // returns false (this is wrong)
    </script>
    <object id="test" />
</body>

VS VS

<html>
<body>
    <object id="test" />
    <script type="text/javascript">
        var foo = document.getElementById("test");
        console.log(typeof foo); // returns function (this is wrong)
        console.log(foo instanceof Function); // returns false
        console.log(foo instanceof Object); // returns true (this is correct)
        console.log(foo instanceof HTMLElement); // returns true (this is correct)
        console.log(foo instanceof Node); // returns true (this is correct)
    </script>
</body>

So basically if the script is below the object, typeof behaves strangely but if the script is above the object instanceof behaves strangely. 所以基本上如果脚本在对象下面,typeof表现得很奇怪,但是如果脚本在对象instanceof之上,则表现得很奇怪。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM