JavaScript:事件处理程序:在哪里声明变量 - 本地或闭包(vs开销)? [英] JavaScript: Event Handlers: Where to declare variables - local or closure (vs overhead)?

查看:108
本文介绍了JavaScript:事件处理程序:在哪里声明变量 - 本地或闭包(vs开销)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现自己正在写各种包含事件处理程序的函数。最好在父函数(closure)的根部声明处理函数所需的变量,特别是如果它们是jQuery选择,多个处理程序需要的常量,或者我不想要的一些预先计算重复每次en事件被触发。一个简单的例子:

I find myself writing various functions which contain event handlers. It feels preferable to declare the variables required by the handler functions at the root of the parent function (closure), especially if they are jQuery selections, constants required by more than one handler, or some pre-computations needed which I wouldn't want to repeat each time en event is fired. A simple example:

var touchDrag = function() {

    var x, y, i;
    var $mySelection = $('.selection');

    $('#some-elem').on( 'touchmove', function(e) {

        x = something;
        y = something;
        i++;
        $mySelection.doSomething();

        // more code..
    });
}  

我理解,保持变量范围尽可能小是一个好习惯。但是,对于频繁发生的事件,如 .scroll() touchmove ,在我看来,

However, I often see handler variables declared inside the handler functions (local). Asked a couple of coders, some debate ensued but not a clear answer.

推荐答案

一般来说,一个事件被触发时,变量应该在需要它的最小范围内定义。因此,如果一个变量只是在 touchmove 事件的实际处理过程中需要,并且它不会从一个事件到下一个事件携带状态,那么我通常会声明它实际的touchmove事件处理程序,所以它的范围是尽可能小,它是垃圾收集时,不使用。

解决方案

当然,有可能从声明它在较高的范围,如:

In general a variable should be defined in the smallest scope in which it is needed. So, if a variable is only needed during the actual processing of a touchmove event and it does not carry state across from one event to the next, then I would generally declare it in the actual touchmove event handler so its scope is as small as possible and it is garbage collected when not being used.


  1. 预先计算。 ,你宁愿计算一次,并保持方便。如果这些是用户触发的事件,那么小的预先计算的性能实际上与用户时间无关。

There are, of course, exceptions that might benefit from declaring it at a higher scope such as:

保留状态一个事件发生到下一个。这需要将变量声明为更高级别,以便它可以从一个事件持续到下一个事件。

  1. Precomputation. Rather than compute something everytime you need it, you'd rather compute it once and keep it handy. If these are user triggered events, then performance of a small precalculation is rarely actually relevant vs. user time.

与其他代码共享如果变量中的值由同一上下文中的其他处理程序共享,那么显然您必须将其声明为足够高的级别,以便所有需要访问它的用户都可以使用。

Preserve state from one occurrence of the event to the next. This requires declaring the variable at a higher level so that it can persist from one event to the next.

这是一个常见的例子,它可能是一个事件想要启动而另一个事件可能要停止的计时器。这里有一些原因要避免在更高的范围内声明变量,这样它们的生命周期更长:

Shared with other code. If the value in the variable is shared by other handlers in the same context, then obviously you have to declare it at a high enough level that it's available for all who want access to it. A common example of this might be a timer that one event wants to start and another event might want to stop.


  1. 您可以无意中创建一些内存泄漏。如果你缓存一个DOM元素,然后你的代码中的其他地方你或其他人决定替换该DOM元素,现在你有一个DOM元素的JS代码,将阻止它被垃圾收集。

Here are some reasons to avoid declaring variables at a higher scope which gives them a longer lifetime:

陈旧的值。上述同样的情况会导致缓存变量的值错误。

  1. Memory Leak. You can inadvertently create some memory leaks. If you're caching a DOM element and then elsewhere in your code you or someone else decides to replace that DOM element, now you have a reference to that DOM element in your JS code that will keep it from getting garbage collected.

代码(可选)如果您需要获取或计算所需的时间,清晰度和稳健性。如果你有一组变量在更高的范围声明,然后一组函数,每个使用这些变量,它不是很清楚谁在使用什么。如果这些实际上是可以互相调用的函数,你有各种各样的可能性,一个函数调用另一个函数使用的变量。认为它是逻辑极端,这正是为什么局部变量比全局变量更好。

Stale values. The same scenario above can lead to a wrong value in a cached variable. There is always less risk of a stale value if you fetch or compute as needed rather than save the value over a long period of time.



Code Clarity and Robustness. If you've got a set of variables declared at a higher scope and then a bunch of functions, each of which uses some of those variables, it is not very clear who is using what. If these are actually functions that can call each other, you have all sorts of possibilities for one function to trounce the variables being used by another function. Taken to it's logical extreme, this is exactly why local variables are preferable to global variables. While a one level higher scope isn't as bad as a global variable, it still has some of the same issues.

hr>

此外,响应您的一个关注,声明和初始化局部变量不是一个大开销,除非计算初始值的工作是一个耗时的任务。但是在你的例子中,只要将 var x 移动到使用它的函数中,函数启动时性能就不会明显下降,事实上,甚至提高了函数执行期间的性能,因为访问局部变量比访问更高范围的变量更快(在检查更高范围之前,首先检查局部命名空间的变量)。


Also, in response to one of your concerns, declaring and initializing a local variable is not a "big overhead" unless the work to compute the initial value is a time consuming task. But in your example, simply moving var x into the function who uses it is not going to be a noticeable drop in performance when the function starts up and, in fact, it might even improve the performance during the execution of the function because accessing local variables is faster than accessing variables at a higher scope (the local namespace is checked for a variable first before higher scopes are checked).

对于现在已经添加到你的问题的 $ mySelection 变量,我将它声明在需要它的最小范围内 until /除非您有任何数据/信息,其初始化性能实际上导致您的问题。一般来说,简单的选择器搜索操作在现代CPU上速度非常快。

As for the $mySelection variable you've now added to your question, I would declare it inside the smallest scope where it is needed until/unless you have any data/information that its initialization performance is actually causing you a problem. In general, simple selector search operations are pretty darn fast on modern CPUs.

与几乎所有的性能问题 - 试图在你有任何证据之前提前解决性能问题它实际上是一个问题很少有效地利用时间或理由偏离最好的编码实践。如有疑问,请尽可能保持您的代码尽可能简单和自给自足。

As with pretty much all performance issues - trying to solve a performance issue prematurely before you have any evidence that it is actually an issue is rarely an effective use of time or a reason to diverge from the best coding practices. When in doubt, keep your code as simple and self-contained as possible.

这篇关于JavaScript:事件处理程序:在哪里声明变量 - 本地或闭包(vs开销)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆