gdo*_*ica 56 javascript performance jquery
这里的人经常建议缓存jQuery
从DOM
元素创建的对象,就像使用以下代码一样:
$('#container input').each(function() {
$(this).addClass('fooClass');
$(this).attr('data-bar', "bar");
$(this).css('background-color', 'red');
});
Run Code Online (Sandbox Code Playgroud)
gdo*_*ica 53
在jQuery 标记信息中出现此警告:
jQuery函数$()很昂贵.反复调用它是非常低效的.
嗯...这对于字符串选择器来说是正确的,它会被正则表达式解析以找出它们是什么:
quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/
Run Code Online (Sandbox Code Playgroud)
然后,如果字符串是一个选择器(除了id
),jQuery遍历DOM以找到与其昂贵的find
函数匹配:
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
}
Run Code Online (Sandbox Code Playgroud)
所以是的,这是昂贵的,但这只适用于选择者!
如果我们传递一个DOMElement
,jQuery所做的唯一操作就是将DOMElement参数保存为新创建的jQuery对象的上下文,并将上下文的长度设置为1:
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector; // Selector here is a DOMElement
this.length = 1;
return this;
}
Run Code Online (Sandbox Code Playgroud)
我用jsPerf做了一些测试,我发现确实缓存jQuery对象只有一点效果:
在Chrome中它的速度只有7%.(在IE中,它有点重要:12%.)
SLa*_*aks 14
要回答第二个问题,请查看来源:
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
Run Code Online (Sandbox Code Playgroud)
cli*_*ity 10
关于性能差异,如果您正在寻找两者之间的直接比较,那么删除任何可能会导致结果偏差的额外代码会很有帮助,例如DOM选择和其他不直接相关的方法.
在更真实的世界环境中,相对差异很小,因为您的测试显示
另外要记住的是,每次创建jQuery对象时,都需要为其分配内存,这会增加垃圾收集器需要完成的工作.
所以我认为人们建议缓存的原因有点原则性.正在进行额外的工作,虽然它通常不会产生明显的影响,但最终还是需要一些可以轻松避免的开销.
所有运行时性能测试都遗漏的一件事是另一个主要考虑因素:
网络带宽.
缓存$(this)
到局部变量通常会减小脚本的大小,特别是在缩小时(因为this
不能从四个字符减少).
考虑:
function hello(text) {
$(this).attr();
$(this).css();
$(this).data();
$(this).click();
$(this).mouseover();
$(this).mouseleave();
$(this).html(text);
}
hello('Hello world');
Run Code Online (Sandbox Code Playgroud)
Closure编译器的缩小输出是
function hello(a){$(this).attr();$(this).css();$(this).data();$(this).click();$(this).mouseover();$(this).mouseleave();$(this).html(a)}hello("Hello world");
Run Code Online (Sandbox Code Playgroud)
这节省了39个字节(20%).现在考虑:
function hello(name) {
var $this = $(this);
$this.attr();
$this.css();
$this.data();
$this.click();
$this.mouseover();
$this.mouseleave();
$this.html(name);
}
hello('Hello world');
Run Code Online (Sandbox Code Playgroud)
缩小的输出是
function hello(b){var a=$(this);a.attr();a.css();a.data();a.click();a.mouseover();a.mouseleave();a.html(b)}hello("Hello world");
Run Code Online (Sandbox Code Playgroud)
这节省了74个字节(37%),几乎使我们的字节节省了一倍.显然,在大型脚本中实际节省的成本会更低,但您仍然可以通过缓存来大幅减少脚本的大小.
真的,缓存只有一个好处$(this)
.您可以获得微不足道但可测量的运行时性能提升.更重要的是,您可以减少通过线路传输的字节数,并直接转换为更多的美元,因为更快的页面加载等于更多的销售.
当你以这种方式看待它时,你实际上可以说重复而不是缓存是可以量化的美元成本$(this)
.