2011-03-30 80 views
4

在对对象执行typeof和instanceof时,我看到了矛盾的结果。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” 被恢复 “功能”,但 “富的instanceof功能” 返回false。

这对我没有意义。一个对象怎么能有一个类型的函数,但不是一个函数的实例?此外,我预计“typeof foo”返回“对象”。

+1

可能的重复[为什么instanceof返回false为一些文字?](http://stackoverflow.com/questions/203739/why-does-instanceof-return-false-for-some-literals) – 2011-03-30 20:11:24

+1

当我做“foo instanceof Object”它返回true。我不认为这个对象是字面的,但我可能是错的... – treaint 2011-03-30 20:16:48

+1

你使用什么浏览器? ['document.getElementById'](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-getElBId)返回的值不应该是函数而是[Element](http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-745549614)或'null'的对象。 – Gumbo 2011-03-30 20:23:29

回答

2

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

总之,所有投注都关闭。不要依赖其记录的API之外的主机对象的行为。

相关的引用:

0

我不知道为什么“功能”返回了<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> 
说明

所以在这种情况下,它实际上是typeof行为奇怪,而不是我能看到is documented的方式。

-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上述奇怪的行为。

+0

在您的第一个测试中添加一行:console.log(foo === null),我期望它会返回true。这是因为脚本运行时元素不存在,所以getElement返回null。其他显示与foo为空一致。 – HBP 2011-03-30 22:15:55

+0

由于历史原因,这似乎只能工作,因为'typeof null'返回''object''。 'getElementById'方法不返回元素,因为它还没有被解析。 – Oriol 2015-02-15 19:38:49

1

Safari浏览器返回 '功能' 为的typeof document.getElementsByTagName( 'P')

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

即使在例外没有发现的情况下,测试我们的前概念也是很好的。

此外,调试器是可爱的,但他们并不总是报告相同的值作为他们的浏览器。

0

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

例如,你可以创造开始使用var myElement =新的HTML元素()

+0

'document.getElementById'不返回函数。但它可能会返回可调用的对象,如'object'或'embed'。只有在这种情况下'typeof'才会返回'“function”'。 'HTMLElement'是一个函数,但不是构造函数,所以'new HTMLElement'会抛出。 – Oriol 2015-02-15 20:10:50

1

objectembed HTML元素是主机对象自己的元素。

ECMAScript3 11.4.3没有定义什么typeof应该返回这些。返回值的对象表是

  • 对象(本机和没有实现[[呼叫]]):"object"
  • 对象(本地和器具[呼叫]]):"function"
  • 对象(主机):实现相关的

然而,返回"function"与ECMAScript5 11.4.3一致:

  • 对象(本机和没有实现[[呼叫]]):"object"
  • 对象(本机或主机和不执行[[呼叫]]):"function"
  • 对象(主机和做不实现[[Call]]):除了可能不是"undefined""boolean", "number""string"之外的实现定义。

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

这在Bug 268945说明:

  • Comment #15,由Boris Zbarsky:

    的[[调用]]是对DOM侧非常故意:这些是可调用的对象。

  • Comment #16,由汤姆·舒斯特:

    此错误是无效的,这些对象有一个[[呼叫]]内部方法和 ES5 11.4.3明确地说“对象(本地或_host_并执行执行 [[Call]])“=>”function“。

由于objectembed HTML元素实施内部[[呼叫]]属性,它们是可调用对象。然而,它们不是功能:

4.3.24功能

即在内置 Function构造一个标准的实例,并且可以被调用作为子程序对象类型的构件

object HTML元素继承自HTMLObjectElement.prototypeembed来自HTMLEmbedElement.prototype的HTML元素。

原型链继续

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

有因为它们不是从Function.prototype继承的,所以它们不是Function实例。

+0

很酷#sharp – Bellash 2015-04-13 10:53:25