JavaScript使用显式的self/window对象来提高性能

3

我在MSDN上读到,为了提高脚本效率,你可以使用self来使隐式窗口引用变得明确。

  1. 你知道这是真的吗?这是否意味着例如调用self.location比在window对象之前不带location更有效率?

  2. 由于MSDN文本是指self而不是window,所以只有使用self才会发生性能提高吗? 根据此处windowselfwindow.self是相同的,因此我们使用什么并不重要,我只是想确保。

  3. 此外,根据MSDN所述,调用window.self应该比调用self更具有性能优势,因为后者是window的一个属性,因此通过调用window.self,我们使用了一个显式引用。

谢谢


2
好的,“window”也是“window”的属性 :-) - Pointy
2个回答

2

这是一种微小的优化,实际上完全浪费时间,但值得一提的是,常见的惯用语是像这样编写JavaScript:

(function(window, undefined) {
  // your code, thousands of lines of sheer beauty
})(this);

这将为您提供对"window"的本地引用以及可靠的"undefined"变量。为什么这是浪费时间?因为对于任何普通代码,您所说的最多只有一两毫秒的执行时间被削减。没有人会注意到这一点。确保您实际使用的算法适合您编写的任何操作,并让Javascript解释器/JIT开发人员为您削减这些毫秒。如果您过于沉迷于此类事情,您可能最终会得到运行速度更慢的代码,因为您将做出不被解释器优化的奇怪操作。

我知道性能的提升(如果有的话)非常小,但这只是我的纯好奇心。你的代码看起来很有趣,能否再解释一些?我不明白我为什么需要它,窗口在全局范围内为什么需要一个本地引用?那里的'undefined'参数是什么意思?谢谢。 - Marco Demaio
2
你不一定需要一个本地引用,但是“window”只是一个属性名称,它可以被重新赋值。通过从全局上下文传递“this”,您可以更好地保证本地的“window”将引用正确的内容。此外,由于它是一个本地变量,所以比引用全局“window”要快一点。 “undefined”也是类似的: “undefined”只是一个属性,可以被更改。通过传递参数,您可以在代码中使用一个真正的未定义变量。同样,这只是一个现代惯例(请参见jQuery)。 - Pointy
1
你也可以使用 var undefined = void 0 来设置 undefined,这在其他开发人员可能调用使用未设置参数的函数时非常有用。如果该开发人员意外地设置了参数,则可能会导致问题。 - Andy E
4
这种优化还可以让JavaScript压缩工具将window参数重命名为较短的名称,而当window指向全局对象时就无法做到这一点。 - Kevin Hakanson

1

虽然这只是微小的优化,但直接属性引用总是比变量查找快。当你写location时,会执行以下操作:

  1. 在当前作用域中查找声明的location,如果找到则返回并退出。
  2. 向上一级作用域移动。
  3. 如果作用域不是全局的,则返回1。如果作用域是全局的,则检查全局作用域中是否有location,如果找到则返回,否则抛出未声明变量错误。

类似的情况是使用with语句创建对象属性作用域。对于self,它也是window的属性。 self是对window的引用,因此window.location应该比window.self.location更快。还要记住,实现可能不同,因此在不同的浏览器中可能会有所不同。

如Pointy所指出的那样,大多数开发人员不必担心像这样的微优化。这种差异是微秒级的,对最终用户完全不可察觉。 更多阅读:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接