在对象中存储文档和 window 引用以获得更好的性能

Storing document and window references in an object to get better performance

我有一个问题,不知道我做对了什么。

我在我的插件中的对象或全局变量中定义 windowdocument,如下所示:

var myplugin = {
     document : document || {},
     window : window || {}
};

当我需要时这样调用之后:

myplugin.window.location.href = 'http://flyflyflymachine.etc';

我想知道我是否获得了更好的性能还是不必要的?

您似乎担心 windowdocument 不存在。例如,如果这段代码是 运行 来自 Worker 或 NodeJS 脚本,它会抛出一个错误。

所以你可以 "optimize" 这有两种方式:

使用带有 this 关键字的命名空间(在全局范围内,this 将引用全局对象)

var myPlugin = {};
(function myPluginNS(_global) {
  myPlugin.window = _global;
  myPlugin.document = _global.document || {};
})(this);

使用老式的 try-catch

var myPlugin = {};
try {
  myPlugin.window = window;
} catch (e) {
  myPlugin.window = {};
}
try {
  myPlugin.document = document;
} catch (e) {
  myPlugin.document = {};
}

诚然,这不是真正的 "optimization",但它至少可以确保您的代码可以 运行 在各种 JS 中 运行 次。

至于性能,是的,缓存可以提供帮助,但您并未在此处缓存任何内容。仅将一个查找替换为另一个查找(yourplugin.document vs window.document)。

实际上在那种情况下,document 速度更快,但除非你在一个紧密的循环中调用它几千次,否则不要为这些极小的优化而烦恼。

理论上,这种纳米优化更适用于在根据 IIFE 而不是使用对象文字初始化器定义插件时创建的嵌套函数。

当代码引用对象变量时,javascript 引擎必须首先搜索当前词法范围记录,然后搜索任何父词法范围记录,直到找到或证明没有找到变量或对象定义已定义。

词法范围记录是为使用 let 变量定义的 for 循环和用于保存参数和变量的函数创建的。因此,在深度嵌套的 for 循环中,在深度嵌套的函数中,在找到 windowdocument.

之前,可能需要检查许多范围记录

制作全局或外部函数引用的副本可以减少要搜索的范围记录的数量。仅当制作副本的开销小于 JavaSript 引擎搜索中间作用域记录的开销乘以外部引用的使用次数时,才会出现净性能增益。这在实践中可能既罕见又难以证明,如果增益很小。

post 中由 "Object object" 初始化器而不是 IIFE 组成的插件定义不符合加速对象引用搜索的标准,实际上可能会减慢速度下来。