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

时间:2011-03-30 20:06:49

标签: javascript

在对象上执行typeof和instanceof时,我看到了相反的结果。

我有以下测试页:

<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”正在返回“功能”但是 “foo instanceof Function”返回false。

这对我没有意义。对象如何将类型设为函数但不是函数的实例?另外,我希望“typeof foo”返回“object”。

6 个答案:

答案 0 :(得分:2)

重要的事实是DOM元素(例如,使用document.getElementById()获得)不是本机JavaScript对象。相反,它们是主机对象。因此,它们不受适用于本机JavaScript对象的通常规则的约束,并且它们的行为将(非常合理地)从一个浏览器到下一个浏览器变化很大。

简而言之,所有赌注都已关闭。不要依赖于其记录的API之外的宿主对象的行为。

相关参考资料:

答案 1 :(得分:1)

Safari为 typeof document.getElementsByTagName('p')返回'功能',

这给了我一段时间以前的糟糕时间,当时我假设所有客户都会返回'对象'。

测试我们的前概念是好的,即使异常没有发生也是如此。

此外,调试器很可爱,但它们并不总是报告与浏览器相同的值。

答案 2 :(得分:1)

objectembed HTML元素是主机对象。

ECMAScript3 11.4.3未定义typeof应返回的内容。对象的返回值表是

  
      
  • 对象(原生且未实现[[Call]]):"object"
  •   
  • 对象(native和implements [[Call]]):"function"
  •   
  • 对象(主机):依赖于实现
  •   

但是,返回"function"与ECMAScript5 11.4.3

一致
  
      
  • 对象(原生且未实现[[Call]]):"object"
  •   
  • 对象(本机或主机并实现[[Call]]):"function"
  •   
  • 对象(主机且未实现[[Call]]):实现定义,但可能不是"undefined""boolean",   "number""string"
  •   

objectembed HTML元素是具有内部[[Call]]属性的对象,因此typeof必须返回"function"

Bug 268945中解释了这一点:

  • Comment #15,作者:Boris Zbarsky:

      

    [[Call]]在DOM方面是非常有意的:这些是​​可调用的对象。

  • Comment #16,汤姆舒斯特:

      

    这个bug无效,这些对象有[[Call]]内部方法和   ES5 11.4.3明确地说“对象(本机或_host_并且确实实现   [[Call]])“=&gt;”function“。

由于objectembed HTML元素实现了内部[[Call]]属性,因此它们是可调用对象。但是,它们不是功能:

  

4.3.24功能

     

Object类型的成员,它是标准内置的实例   Function构造函数,可以作为子例程调用

object HTML元素继承自HTMLObjectElement.prototype的{​​{1}}和embed HTML元素。

原型链继续

  • HTMLEmbedElement.prototype
  • HTMLObjectElement.prototype
  • HTMLElement.prototype
  • Element.prototype
  • Node.prototype

因此,它们不是Object.prototype个实例,因为它们不会从Function继承。

答案 3 :(得分:0)

我不确定为什么'{1}}节点返回'function',但<object>失败的原因是因为它基本上是对构造函数的检查,其区别可以说明如下所以

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> 表现得很奇怪,而不是我能看到is documented的方式。

答案 4 :(得分:0)

在第一个示例中,运行脚本时此dom元素不存在。 在你的第二个,它的答案是正确的,第二个是typeof和constructor之间的区别。 typeof返回一个函数,因为document.getElementById返回一个函数。 构造函数告诉您该函数的名称“HTMLElement”。

例如,你可以用var myElement = new HTMLElement()

开发自己的元素

答案 5 :(得分:-1)

我发现了一些额外的奇怪行为。

如果你将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

<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>

所以基本上如果脚本在对象下面,typeof表现得很奇怪,但是如果脚本在对象instanceof之上,则表现得很奇怪。