Javascript: typeof and instanceof results contradict?

I see conflicting results when doing typeof and instanceof for an object.

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" returns a "function", but the function foo instanceof Function returns false.

That doesn't make sense to me. How can an object have a type but not be an instance of a function? Also, I was expecting "typeof foo" to return an "object".

+4
source share
6 answers

An essential fact is that DOM elements (obtained, for example, using document.getElementById() ) are not native JavaScript objects. Instead, they are host objects. Thus, they do not obey the usual rules that apply to native JavaScript objects, and their behavior (quite legitimately) varies greatly from one browser to another.

In short, all bets are disabled. Do not rely on the behavior of host objects outside of their documented API.

Related links:

+2
source

Safari returns a function for typeof document.getElementsByTagName ('p') ,

which gave me a bad time ago when I assumed that all clients would return an โ€œobjectโ€.

It is good to test our pre-concepts, even if the exception does not make sense.

In addition, debuggers are great, but they do not always report the same values โ€‹โ€‹as their browser.

+1
source

object and embed HTML elements are host objects.

ECMAScript3 11.4.3 did not determine what typeof should return for them. The return table for objects was

  • Object (native and does not implement [[Call]]): "object"
  • Object (native and implements [[Call]]): "function"
  • Object (host): implementation dependent

However, the return of "function" corresponds to ECMAScript5 11.4.3 :

  • Object (native and does not implement [[Call]]): "object"
  • Object (native or host and implements [[Call]]): "function"
  • Object (the host does not implement [[Call]]): The implementation, with the exception of, may not be "undefined" , "boolean" , "number" or "string" .

object and embed HTML elements are objects with an internal [[Call]] property, so typeof should return "function" .

This is explained in Error 268945 :

  • Comment No. 15 , Boris Zbarsky:

    [[Call]] is very intentional on the DOM side: these are called objects.

  • Comment # 16 , Tom Schuster:

    This error is invalid, this object has an internal [[Call]] method and ES5 11.4.3 explicitly says "Object (native or _host_) and implements [[Call]])" => "function".

Since the object and embed HTML elements implement the internal [[Call]] property, they are callable objects. However, they are not functions:

4.3.24 function

a member of type Object, which is an instance of the standard built-in Function and which can be called as a routine

object HTML elements inherit from HTMLObjectElement.prototype and embed HTML elements from HTMLEmbedElement.prototype .

The prototype chain continues

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

Therefore, they are not Function instances because they are not inherited from Function.prototype .

+1
source

I'm not sure why the โ€œfunctionโ€ is returned for the <object> node, but the reason for the instaceof Function does not work, because it is essentially a check against the constructor, the difference in which can be illustrated as follows

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

Thus, in this case, in fact, typeof behaves strangely, and not in the way that the documentation that I see is documented .

0
source

In the first example, this dom element does not exist when the script is executed. In the second case, the answers are correct in the second difference between typeof and constructor. typeof returns a function because document.getElementById returns a function. the constructor tells you the name of this function "HTMLElement".

you could, for example, invent your own elements, starting with var myElement = new HTMLElement ()

0
source

I discovered some strange behavior.

If you move javascript code over an object, then typeof works correctly, but instanceof does not work.

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

So basically, if the script is below the object, typeof behaves strangely, but if the script is above the instanceof object, it behaves strangely.

-1
source

Source: https://habr.com/ru/post/1345940/


All Articles