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

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

4

2 回答 2

4

让我们分解一下:

Object.prototype

这为我们提供了作为Object变量原型的 JavaScript 对象。什么是原型?请允许我引用 Yehuda Katz 的优秀博文(非常值得一读):

如果您尝试查找对象上的键但未找到,JavaScript 将在原型中查找它。它将遵循“原型链”,直到它看到一个空值。在这种情况下,它返回未定义。

接下来,我们有:

Object.prototype.toString

这将返回原型toString上的函数。Object可以使用它们的函数调用 JavaScriptcall函数。这里有几个例子:

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

所以它基本上只是一个通用的 toString 函数,它返回一个字符串,描述你作为参数提供的任何内容call。请注意,在这些示例中,参数是对象本身,因此它们返回将自身描述为对象的字符串。如果我们通过了window.HTMLElement呢?

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

所以现在我们看到它返回了一个包含 substring 的字符串"Constructor",这意味着它很可能是一个构造 HTML 元素的对象。最后我们可以理解完整的表达方式:

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

因为"Constructor"是一个子字符串,indexOf所以返回 19,即 > 0。所以基本上,这个表达式似乎是检查是否window.HTMLElement使用后缀“构造函数”来识别自己,我猜这可能是某种浏览器识别检查。

(注意:在写这篇文章时,我测试了使用 Safari 的 Web Inspector 控制台评估这些表达式,但你也可以使用 Chrome 或其他浏览器的控制台来测试这样的东西。)

于 2013-03-18T06:56:58.280 回答
2
  • Object是 javascript 中(几乎)所有类型都继承的类(构造函数)。
  • Object.prototype是几乎所有对象的原型链中都能找到的对象。
  • Object.prototype.toString是在不覆盖它的对象上调用的方法。
  • .call,当在函数上调用时,以第一个参数作为上下文调用该函数。func.call(a)类似于a.func=func; a.func()。不同之处在于 while undefined.toString()is a TypeError,Object.prototype.toString.call(undefined)工作得很好。
  • HTMLElement是一个继承自 HTML 元素的类。但是,这不是规范要求的,并且在 Internet Explorer 中并非如此,其中 HTML 元素没有原型并且HTMLElement那里不存在构造函数。既然window是浏览器环境中的全局对象,就和没有被局部变量遮蔽window.HTMLElement一样,HTMLElement 如果存在的。如果它不存在,读取HTMLElement会抛出一段ReferenceError时间window.HTMLElement返回undefined
  • 所以,Object.prototype.toString.call(window.HTMLElement)除了HTMLElement.toString() 在 IE 中工作并使用正确的toString. 它总是返回一个String.
  • indexOf是一个 String 函数,它查找其子字符串的第一次出现,-1如果子字符串不存在则返回。.indexOf('Constructor') > 0检查字符串是否包含,并且不以 . 开头"Constructor"

因此,此方法在调用 on 时确定是否toString包含。该规范要求"Constructor"HTMLElement

...
4) 令 class 为 O 的 [[Class]] 内部属性的值。
5) 返回作为连接三个字符串“[object”、class 和“]”的结果的字符串值。

因此,这会检查HTMLElement's[[class]]是否为Constructor

最后将检查结果分配给变量isSafari。这表明在哪些环境中这是正确的。这段代码的作者假设返回值包含"Constructor"在 Safari 中,在每个版本的 Safari 中,并且仅在 Safari 中。

作为参考,在 Chrome 中,Object.prototype.toString.call(HTMLElement)返回"[object Function]".

于 2013-03-18T07:07:49.463 回答