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

时间:2014-01-29 22:57:09

标签: javascript

好的,我正在尝试做的是当点击一个按钮时会产生以下超时功能触发器:

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

我遇到的问题是因为变量lightnum会立即重复使用,所以当这个超时触发时,它会在创建settimeout时引用lightnum的当前值而不是lightnum的值。我在这里寻找的功能是当setTimeout在3秒后触发时它引用了最初创建时的lightnum值。

http://jsfiddle.net/657q2/1/

3 个答案:

答案 0 :(得分:4)

首先,该代码应该是一个正确的函数而不是字符串。

关于你的问题,它修复如下:

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;等)的函数内部创建一个本地副本。但是,这仍然不起作用,因为这次调用回调时它将对最后一次调用此函数时copy的最后一个值进行操作(可能但不一定与原始代码的行为相同) )。

您真正想要做的是将lightnum的当前值放在回调代码可以访问的 的某个位置;在JS中,唯一的方法是将它作为参数传递给函数。这需要上面那个时髦的“函数返回函数”语法:内部函数是实际需要的回调函数,外部函数是一个“防火墙”,它可以阻止任何外部干涉有问题的变量。

答案 1 :(得分:1)

使用闭包而不是字符串:

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
);

答案 2 :(得分:1)

“Jon”和“Ted Hopp”有正确的答案,但我可能只是在这里添加为什么功能更好:

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