Javascript 在传递变量期间保持原始值

Javascript 在传递变量期间保持原始值,javascript,Javascript,好的,我想做的是当点击一个按钮时,函数触发器会产生以下超时: setTimeout("if (document.getElementById(lightnum).style.backgroundColor=='green'){document.getElementById(lightnum).dataset.dead=1;document.getElementById(lightnum).style.backgroundColor='red';}", 3000); 我遇到的问题是,因为变量li

好的,我想做的是当点击一个按钮时,函数触发器会产生以下超时:

setTimeout("if (document.getElementById(lightnum).style.backgroundColor=='green'){document.getElementById(lightnum).dataset.dead=1;document.getElementById(lightnum).style.backgroundColor='red';}", 3000);
我遇到的问题是,因为变量lightnum被立即重用,所以当这个超时触发时,它引用的是lightnum的当前值,而不是创建settimeout时lightnum的值。我在这里寻找的功能是当setTimeout在3秒后触发时,它引用最初创建时lightnum的值


使用闭包而不是字符串:

setTimeout(
    (function(ln) {
        return function() {
            if (document.getElementById(ln).style.backgroundColor=='green') {
                document.getElementById(ln).dataset.dead=1;
                document.getElementById(ln).style.backgroundColor='red';
            }
        };
    }(lightnum)),
    3000
);

使用闭包而不是字符串:

setTimeout(
    (function(ln) {
        return function() {
            if (document.getElementById(ln).style.backgroundColor=='green') {
                document.getElementById(ln).dataset.dead=1;
                document.getElementById(ln).style.backgroundColor='red';
            }
        };
    }(lightnum)),
    3000
);

首先,该代码应该位于正确的函数中,而不是字符串中

关于您的问题,它是这样修复的:

var callback = (function(target) {
    return function() {
        if (target.style.backgroundColor == 'green') {
            target.dataset.dead = 1;
            target.style.backgroundColor = 'red';
        }
    };
})(document.getElementById(lightnum));

setTimeout(callback, 3000);
原始代码的问题在于原始回调中的
lightnum
在调用回调时会计算为其值,正如您已经看到的那样。相反,您想要的是以某种方式将其“冻结”到其初始值

这样做的一个尝试是在设置超时的函数中创建本地副本(
var copy=lightnum;
etc)。但是,这仍然不起作用,因为这次调用回调时,它将对上次调用此函数时的
copy
的最后一个值进行操作(可能但不一定与原始代码的行为相同)


您真正想要做的是将当前值
lightnum
放在只有回调代码才能访问的地方;在JS中,唯一的方法是将其作为参数传递给函数。这就需要使用上面时髦的“返回函数的函数”语法:内部函数是实际需要的回调函数,外部函数是一个“防火墙”,防止任何外部干预所讨论的变量。

首先,代码应该在一个适当的函数中,而不是字符串中

关于您的问题,它是这样修复的:

var callback = (function(target) {
    return function() {
        if (target.style.backgroundColor == 'green') {
            target.dataset.dead = 1;
            target.style.backgroundColor = 'red';
        }
    };
})(document.getElementById(lightnum));

setTimeout(callback, 3000);
原始代码的问题在于原始回调中的
lightnum
在调用回调时会计算为其值,正如您已经看到的那样。相反,您想要的是以某种方式将其“冻结”到其初始值

这样做的一个尝试是在设置超时的函数中创建本地副本(
var copy=lightnum;
etc)。但是,这仍然不起作用,因为这次调用回调时,它将对上次调用此函数时的
copy
的最后一个值进行操作(可能但不一定与原始代码的行为相同)

您真正想要做的是将当前值
lightnum
放在只可由回调代码访问的地方;在JS中,唯一的方法是将其作为参数传递给函数。这就需要使用上面时髦的“返回函数的函数”语法:内部函数是实际需要的回调函数,外部函数是一个“防火墙”,防止任何外部干预所讨论的变量。

“Jon”和“Ted Hopp”有正确的答案,但我可以在此补充为什么函数更好:

  • 正如Barmar所说,字符串评估将在全局范围内进行
  • IDE不会在字符串中突出显示语法,因此它会降低您和其他人对代码的可读性
  • 评估速度较慢
  • 最严重的是,如果字符串的一部分来自不受信任的输入,则可能导致安全问题(例如,如果字符串的一部分来自用户评论数据库,恶意用户可能会在其中添加代码以获取用户的cookie)
  • “Jon”和“Ted Hopp”有正确的答案,但我可以在此补充一下为什么函数更好:

  • 正如Barmar所说,字符串评估将在全局范围内进行
  • IDE不会在字符串中突出显示语法,因此它会降低您和其他人对代码的可读性
  • 评估速度较慢
  • 最严重的是,如果字符串的一部分来自不受信任的输入,则可能导致安全问题(例如,如果字符串的一部分来自用户评论数据库,恶意用户可能会在其中添加代码以获取用户的cookie)

  • 你能不能先
    var tempLightnum=lightnum
    ,然后
    setTimeout(…tempLightnum…,3000)
    ?我试过了,lightnum一秒钟可以有40多个新条目,所以使用虚拟变量是行不通的,因为它们的输入速度太快了。这个变量会像第一个变量一样出错。你能不能先
    var tempLightnum=lightnum
    ,然后
    setTimeout(…tempLightnum…,3000)
    ?我试过了,lightnum一秒钟可以有40多个新条目,所以使用虚拟变量是行不通的,因为它们输入的速度太快了。那个变量会像第一个一样搞砸。谁在否决这些?为什么?我不知道。虽然DV已被删除。在对程序进行另一轮测试后,我注意到同样的问题仍然存在。@泰勒:确保您的回调没有引用任何“从外部”可见的变量(例如,上面显示的
    target
    不可能被回调代码以外的任何人访问)。以上代码保证是正确的,鉴于问题中的信息,没有其他建议。以下是我的JSFIDLE javascript:我不太确定你在之前的评论中的意思。谁在否决这些以及为什么?我不知道。虽然DV已被删除。在对程序进行另一轮测试后,我注意到同样的问题仍然存在。@泰勒:确保您的回调没有引用任何“从外部”可见的变量(例如,上面显示的
    target
    不可能被回调代码以外的任何人访问)。以上代码保证是正确的,并且在给定信息的情况下,没有其他建议