这个语句“Object.prototype”有什么作用?

时间:2013-03-18 06:17:46

标签: javascript dom safari indexof

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

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

2 个答案:

答案 0 :(得分:4)

让我们分解一下:

Object.prototype

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

  

如果您尝试在对象上查找某个键并且找不到该键,   JavaScript将在原型中查找它。它将随之而来   “原型链”,直到它看到一个空值。在这种情况下,   它返回undefined。

接下来,我们有:

Object.prototype.toString

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

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

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

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

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

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

答案 1 :(得分:2)

  • Object是(几乎)javascript中所有类型都继承的类(构造函数)。
  • Object.prototype是可以在几乎所有对象的原型链中找到的对象。
  • Object.prototype.toString是在不覆盖它的对象上调用的方法。
  • .call,在函数上调用时,以第一个参数作为上下文调用该函数。 func.call(a)a.func=func; a.func()类似。不同之处在于,虽然undefined.toString()TypeError,但Object.prototype.toString.call(undefined)的效果非常好。
  • HTMLElement是HTML元素继承的类。但是,规范并不要求这样做,在Internet Explorer中也不是这样,因为HTML元素没有原型,并且那里不存在HTMLElement构造函数。由于window是浏览器环境中的全局对象,window.HTMLElementHTMLElement 相同,如果未被局部变量遮蔽,如果 em>它存在。如果不存在,则在HTMLElement返回ReferenceError时,阅读window.HTMLElement会引发undefined
  • 因此,Object.prototype.toString.call(window.HTMLElement)HTMLElement.toString() 相同,除了它在IE中有效并使用了正确的toString。它始终返回String
  • indexOf是一个String函数,它查找其子字符串的第一个出现,如果子字符串不存在则返回-1.indexOf('Constructor') > 0检查字符串是否包含"Constructor",但不包括toString

因此,此方法会在"Constructor"上调用时确定HTMLElement是否包含HTMLElementThe specification mandates that

  

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

因此,这会检查[[class]]的{​​{1}}是否为Constructor

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

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