'$(this)'的成本是多less?
这里的人们经常build议caching从DOM
元素创build的jQuery
对象,就像这样的代码:
$('#container input').each(function() { $(this).addClass('fooClass'); $(this).attr('data-bar', "bar"); $(this).css('background-color', 'red'); });
- cachingjQuery对象是否真的提高了我们的代码的性能?
- 当您将DOM元素传递给jQuery构造函数时,“幕后”会发生什么?
在jQuery 标签信息中出现这个警告:
jQuery函数$()是昂贵的。 多次调用是非常低效的。
那么…这只适用于stringselect器,用正则expression式来parsing它们是什么:
quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/
然后,如果string是一个select器(除id
),jQuery遍历DOMfind一个匹配与其昂贵的find
function:
} else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); }
所以是的,这是昂贵的,但只有select器才是真的!
如果我们传递一个DOMElement
,那么jQuery唯一的作用是将DOMElement参数保存为新创build的jQuery对象的上下文,并将上下文的长度设置为1:
// Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; // Selector here is a DOMElement this.length = 1; return this; }
我用jsPerf做了一些testing,发现cachingjQuery对象只有一点效果:
在Chrome中,它只有7%的慢。 (在IE中,它有点重要:12%。)
要回答你的第二个问题,请看源代码 :
// Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; }
关于性能差异,如果您正在寻找两者之间的直接比较,那么删除可能导致结果偏斜的任何额外代码(如DOMselect和其他不直接相关的方法)将会很有帮助。
在更真实的世界里,你的testing显示的相对差异很小
另外需要记住的是,每次创build一个jQuery对象时,都需要为其分配内存,这就增加了垃圾回收器需要做的工作。
所以我认为人们提出caching的原因是从某种原则的angular度来看的。 额外的工作正在完成,虽然通常不会有明显的影响,但最终还是需要一些可以轻易避免的开销。
所有运行时性能testing在这里错过的一件事是另一个主要的考虑因素:
networking带宽。
将$(this)
caching到局部variables中通常会减小脚本的大小,特别是缩小时(因为不能从四个字符中减less)。
考虑:
function hello(text) { $(this).attr(); $(this).css(); $(this).data(); $(this).click(); $(this).mouseover(); $(this).mouseleave(); $(this).html(text); } hello('Hello world');
Closure编译器的缩小输出是
function hello(a){$(this).attr();$(this).css();$(this).data();$(this).click();$(this).mouseover();$(this).mouseleave();$(this).html(a)}hello("Hello world");
这节省了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');
缩小的输出是
function hello(b){var a=$(this);a.attr();a.css();a.data();a.click();a.mouseover();a.mouseleave();a.html(b)}hello("Hello world");
这节省了74个字节(37%),节省了将近一倍的字节。 很明显,大型脚本中真实世界的节省将会降低,但是仍然坚持通过caching来显着减less脚本的大小。
真的,caching$(this)
只有一个好处。 你会得到微不足道的,但可衡量的运行时性能提升。 更重要的是,您可以减less通过networking传输的字节数,并且直接转化为更多的美元,因为更快的页面负载等于更多的销售额 。
当你这样看的时候,实际上可以说重复$(this)
并且不caching它会有一个可量化的美元成本 。