简体   繁体   中英

What does this statement “ Object.prototype” do?

var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;

谁能告诉我上面的代码在做什么?

Let's break it down:

Object.prototype

This gives us the JavaScript object which is the prototype of the Object variable. What's a prototype? Allow me to quote from Yehuda Katz's excellent blog post (well worth a read):

If you try to look up a key on an object and it is not found, JavaScript will look for it in the prototype. It will follow the “prototype chain” until it sees a null value. In that case, it returns undefined.

Next, we have:

Object.prototype.toString

This returns the toString function on Object 's prototype. JavaScript functions can be called using their call function. Here's a couple examples:

Object.prototype.toString.call("foo")  # => "[object String]"
Object.prototype.toString.call(5)      # => "[object Number]"

So its basically just a generic toString function, that returns a string describing whatever you give as an argument to call . Note that in these examples, the arguments are Objects themselves, so they return strings describing themselves as object. What if we pass it window.HTMLElement ?

Object.prototype.toString.call(window.HTMLElement)  # => "[object HTMLElementConstructor]"

So now we see it is returning a string that contains the substring "Constructor" , meaning it is likely an object which constructs HTML elements. Finally we can understand the full expression:

Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor')  # => 19

Since "Constructor" is a substring, indexOf returns 19, which is > 0. So basically, this expression appears to check whether or not window.HTMLElement identifies itself using the suffix "Constructor", which I guess may be some kind of browser identification check.

(Note: while writing this, I tested evaluating these expressions using Safari's Web Inspector console, but you could also use Chrome or other browsers' consoles for testing things like this.)

  • Object is the class (constructor) from which (almost) all types in javascript inherit.
  • Object.prototype is the object that can be found in the prototype chain of almost all objects.
  • Object.prototype.toString is the method that gets called on objects that don't override it.
  • .call , when called on a function, calls the function with its first argument as the context. func.call(a) is similar to a.func=func; a.func() a.func=func; a.func() . The difference is that while undefined.toString() is a TypeError , Object.prototype.toString.call(undefined) works perfectly fine.
  • HTMLElement is a class from which HTML elements inherit. However, this is not required by the specification, and is not true in Internet Explorer, where HTML elements don't have a prototype and the HTMLElement constructor does not exist there. Since window is the global object in browser environment, window.HTMLElement is the same as HTMLElement if not shadowed by a local variable, and if it exists. If it doesn't exist, reading HTMLElement throws a ReferenceError while window.HTMLElement returns undefined .
  • So, Object.prototype.toString.call(window.HTMLElement) is the same as HTMLElement.toString() except it works in IE and uses the right toString . It always returns a String .
  • indexOf is a String function that finds the first occurence of its substring, returning -1 if the substring is not present. .indexOf('Constructor') > 0 checks if the string contains, and does not start with, "Constructor" .

So, this method determines if toString contains "Constructor" when called on HTMLElement . The specification mandates that :

...
4) Let class be the value of the [[Class]] internal property of O.
5) Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".

Thus, this checks if HTMLElement 's [[class]] is Constructor .

Finally the check result is assigned to the variable isSafari . This indicates in which environments this is true. The author of this code assumes that the return value contains "Constructor" in Safari, in every version of Safari, and only in Safari.

For reference, in Chrome, Object.prototype.toString.call(HTMLElement) returns "[object Function]" .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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