实际上,这完全取决于您需要该变量存在的位置。JS 会将变量提升到当前范围的顶部(声明的范围),或者如果未声明 var,则创建一个(邪恶的)全局变量。
是否在循环中声明 var 并不重要:
for (var i=0;i<10;i++)
{
var j = 1*2;
}
被翻译成:
var i, j;
for (i=0;i<10;i++)
{
j = 1*2;
}
不过,有几个“经验法则”:
- 如果您使用的是全局变量,那么您可能犯了一个错误
- 如果您在循环中声明一个变量,那么您可能无论如何都不需要该变量
- 如果您没有声明变量,请尝试使用您的脚本执行此操作:
(function()
{
'use strict';
//your code here
}());
并调试它,直到你隐含全局自由。
在您的示例中,您“提供”了show_id
在全局范围内声明(好吧,$(document).ready(callback
无论如何都是范围)或在click
处理程序内声明的选择。也没有什么可以阻止您在each
回调中声明变量,在这种情况下不会有太大区别,但这是另一回事。
在 JS 中,函数都有自己的作用域,你在你需要的作用域中声明一个变量。
话虽如此,只要注意到你的性能标签,你的代码在效率方面就和它一样糟糕。而不是循环遍历行,并绑定事件处理程序:委托事件:
$('#my_table').on('click','tr',function(e)
{
var show_id = e.target.attr('data-show-id');
});
在此代码中,show_id
将在单击处理程序返回后进行 GC,如果您希望show_id
保留它,例如,检查下一行被单击的时间:
$('#my_table').on('click','tr',(function (show_id)
{
return function(e)
{
console.log('show_id was: ' + show_id);
show_id = e.target.attr('data-show-id');
console.log('and is now: ' + show_id);
};
}()));
console.log(show_id);//undefined
变量保持在作用域内(包裹在的函数return function
是声明的作用域show_id
,但它的返回值引用该变量,所以它不是 GC'ed。在返回的函数之外,我们处于更高的作用域,所以我们根本无法访问变量。我们可以做的是暴露它的值:
var someVar = {};
$('#my_table').on('click','tr',(function (show_id)
{
return function(e)
{
show_id = e.target.attr('data-show-id');
someVar.myTableClicks = show_id;
console.log(someVar.myTableClicks);//value of show_id
};
}()));
console.log(someVar.myTableClicks);//undefined
//after a couple of clicks
console.log(someVar.myTableClicks);//some value
现在,我们可以访问show_id
任何我们可以访问的值someVar
。
就个人而言,我更喜欢保留需要一些变量可用的组代码:
var access = (function(timer)
{
var speed = 100,
begin = function(callback, interval)
{
speed = +(interval) || speed;
timer = setInterval(callback, speed);
},
stop = function()
{
clearInterval(timer);
};
return {start: start, stop: stop};
}());
在此示例中,start
和stop
函数都需要访问timer
var,但我不希望外部的任何代码与timer
' 值混淆,所以我只公开这些函数。AFAIK,回调参数函数可以包含timer
或speed
引用,但它们不会引用我试图屏蔽的speed
和变量,因为根据定义,回调函数将在另一个范围内声明,因此它无法访问这个范围。即便如此,如果你想绝对确定,你总是可以这样做:timer
var access = (function(timer)
{
var speed = 100,
begin = function(callback, interval)
{
speed = +(interval) || speed;
timer = (function(timer, speed)
{//masks timer & speed from the higher scope
return setInterval(callback, speed);
}('abc', 'def'));//assign dummy values
timer = setInterval(callback, speed);
},
stop = function()
{
clearInterval(timer);
};
return {start: start, stop: stop};
}());