是否应该间歇性地使用 JavaScript 局部变量来提高性能?
Should JavaScript local variables be intermittently used to improve performance?
考虑以下两段脚本。第一个短了一行并使用了一个更少的变量 $t
,然而,又将 this
转换为 jQuery 对象。
从性能(不是可读性)的角度来看,一个比另一个好吗?
如果第一个更好,是否有人会想要使用第二个,例如我需要将 this
转换为 jQuery 对象一百次?何时应进行此转换是否有任何经验法则?
$(".click").click(function(){
$('body').data('link',$(this));
$("#dialog").data('id',$('#id').val()).data('status',$(this).text()).dialog("open");
});
$(".click").click(function(){
var $t=$(this);
$('body').data('link',$t);
$("#dialog").data('id',$('#id').val()).data('status',$t.text()).dialog("open");
});
它可能更快,因为 $()
做了一些工作来弄清楚你给它的是什么。当您给 $()
一个 DOM 元素时, 极 不太可能重要。如果你不在一个紧密的循环中,那并不重要。处理 click
并不是代码的性能关键位。
当您重复查询 DOM 时,就会出现差异,例如:
$(".foo[data-nifty]").doThis();
$(".foo[data-nifty]").doThat();
$(".foo[data-nifty]").doTheOther();
在那里,您无缘无故地强制重复搜索具有 class foo
和 data-nifty
属性的所有元素的 DOM。现在,除非它处于循环中,否则它可能也无关紧要,但这是您应该注意的地方。如果这三个方法都可以链接,写一个链,或者使用一个临时变量。
一般来说,编写可读代码,尽早并经常进行测试,当您发现实际性能问题时,进行处理。
反之亦然:
$(".foo").click(function() {
var $t = $(this);
$t.doThis();
$t.doThat();
$t.find(".something").not(".hooked").addClass("hooked").on("click", function() {
// Do something here without using `$t`...
});
});
在那里,我们正在点击的 .foo
元素中寻找任何 .something
没有 .hooked
的元素,如果找到,则向其添加点击处理程序。 (这显然是非常人为的;我们会改用事件委托。但假设这是我们真正要写的东西。)
在 理论 中,如果有任何新的 .something
被挂钩,那么它们的事件处理程序将被保留,并且由于它是对单击上下文的关闭, $t
变量保存在内存中,这意味着 $t
变量所指的内容也保存在内存中。因此,我们最终可能会使用比理想情况下更多的内存。 (因为 $t
中的 DOM 元素集不是我们需要保留在 $t
中的东西。)
在实践中,现代引擎可以并且有时会执行 "optimize" 闭包,释放理论上需要保留的变量,如果它们能够向自己证明它们可以做到这一点而不会造成副作用。但是当你不需要的时候依赖它并不理想。在上面,你可以在末尾添加 $t = undefined;
或 $t = null;
来释放它引用的 jQuery 集。调用的上下文和 $t
变量可能仍然保留(除非 JavaScript 引擎优化),但至少 jQuery 集 $t
用于引用不是.
显然,从性能的角度来看,第二个示例更有效。
假设您是一名建筑工人,您正在梯子上修理破损的天花板。你的第一个例子就像你在地板上的工具箱里有你需要的工具。第二个例子就像你的工具带里有工具,你不必爬下梯子去拿工具再爬上去。
考虑以下两段脚本。第一个短了一行并使用了一个更少的变量 $t
,然而,又将 this
转换为 jQuery 对象。
从性能(不是可读性)的角度来看,一个比另一个好吗?
如果第一个更好,是否有人会想要使用第二个,例如我需要将 this
转换为 jQuery 对象一百次?何时应进行此转换是否有任何经验法则?
$(".click").click(function(){
$('body').data('link',$(this));
$("#dialog").data('id',$('#id').val()).data('status',$(this).text()).dialog("open");
});
$(".click").click(function(){
var $t=$(this);
$('body').data('link',$t);
$("#dialog").data('id',$('#id').val()).data('status',$t.text()).dialog("open");
});
它可能更快,因为 $()
做了一些工作来弄清楚你给它的是什么。当您给 $()
一个 DOM 元素时, 极 不太可能重要。如果你不在一个紧密的循环中,那并不重要。处理 click
并不是代码的性能关键位。
当您重复查询 DOM 时,就会出现差异,例如:
$(".foo[data-nifty]").doThis();
$(".foo[data-nifty]").doThat();
$(".foo[data-nifty]").doTheOther();
在那里,您无缘无故地强制重复搜索具有 class foo
和 data-nifty
属性的所有元素的 DOM。现在,除非它处于循环中,否则它可能也无关紧要,但这是您应该注意的地方。如果这三个方法都可以链接,写一个链,或者使用一个临时变量。
一般来说,编写可读代码,尽早并经常进行测试,当您发现实际性能问题时,进行处理。
反之亦然:
$(".foo").click(function() {
var $t = $(this);
$t.doThis();
$t.doThat();
$t.find(".something").not(".hooked").addClass("hooked").on("click", function() {
// Do something here without using `$t`...
});
});
在那里,我们正在点击的 .foo
元素中寻找任何 .something
没有 .hooked
的元素,如果找到,则向其添加点击处理程序。 (这显然是非常人为的;我们会改用事件委托。但假设这是我们真正要写的东西。)
在 理论 中,如果有任何新的 .something
被挂钩,那么它们的事件处理程序将被保留,并且由于它是对单击上下文的关闭, $t
变量保存在内存中,这意味着 $t
变量所指的内容也保存在内存中。因此,我们最终可能会使用比理想情况下更多的内存。 (因为 $t
中的 DOM 元素集不是我们需要保留在 $t
中的东西。)
在实践中,现代引擎可以并且有时会执行 "optimize" 闭包,释放理论上需要保留的变量,如果它们能够向自己证明它们可以做到这一点而不会造成副作用。但是当你不需要的时候依赖它并不理想。在上面,你可以在末尾添加 $t = undefined;
或 $t = null;
来释放它引用的 jQuery 集。调用的上下文和 $t
变量可能仍然保留(除非 JavaScript 引擎优化),但至少 jQuery 集 $t
用于引用不是.
显然,从性能的角度来看,第二个示例更有效。
假设您是一名建筑工人,您正在梯子上修理破损的天花板。你的第一个例子就像你在地板上的工具箱里有你需要的工具。第二个例子就像你的工具带里有工具,你不必爬下梯子去拿工具再爬上去。