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