JavaScript无意中将DOM元素id字符串“转换”为DOM对象引用?

时间:2015-03-04 10:44:36

标签: javascript

让我们假设我有这段代码:

function foo (id_of_dom_element, number){

    document.getElementById(id_of_dom_element).innerHTML=number;
    number = number + 1;
    setTimeout("foo(" + id_of_dom_element + "," + number + ")", 1000);
}

初次调用该函数:

foo("countdown", 0);

会发生什么:

  • 在第一次迭代时,一切都像它应该
  • 然而,在第二次迭代中," id_of_dom_element"不再是字符串而是DOM对象引用??

问题:

  • 为什么会这样(我甚至不知道如何搜索这种现象)?
  • 我该如何防止这种情况?

非常感谢!

2 个答案:

答案 0 :(得分:1)

这是因为您将字符串作为回调函数传递给setTimeout并且您没有注意确保id_of_dom_element作为字符串本身传递,因此它指的是自动创建的变量window[id_of_dom_element](即元素本身)。

这些天将函数作为字符串传递被认为是非常糟糕的做法 - 不要这样做!相反,传递一个匿名函数:

setTimeout(function() {
     foo(id_of_dom_element, number);
}, 1000);

更好的是,您可以封装整个行为:

function elementCounter(id, number) {
    var el = document.getElementById(id);
    (function loop() {
        el.innerHTML = number++;
        setTimeout(loop, 1000);
    })();  // loop is an "immediately invoked function expression"
}

请注意,在此版本中,所有"状态"包含在外部范围的变量中,因此setTimeout调用只需传递对loop函数的引用。

答案 1 :(得分:0)

带有ID的DOM中的所有元素都可通过等于其id名称的变量获得。

第二次调用超时时,在foo方法中,不包括引号,因此不是传递变量"countdown"而是传递变量{{1}这等于DOM对象。您可以将代码更改为

countdown