【发布时间】:2010-02-19 14:15:15
【问题描述】:
我正在玩弄(阅读:学习)Javascript,发现了一些我理解的东西,看起来很奇怪。它与闭包和似乎“失去”其对浏览器重要性的引用有关。
我使用的浏览器是 Chromium 5.0.307.7。
不管怎样,这里有一些代码:
HTMLElement.prototype.writeInSteps = function() {
var i = 0;
var elem = this;
var args = arguments;
function step() {
elem.innerHTML += args[i];
if(i < args.length) {
i += 1;
} else {
elem.innerHTML = "";
i = 0;
}
setTimeout(step, 500);
}
step();
}
这里发生的是第一个参数被写入正确的 HTMLElement,但后面的所有参数都没有。似乎发生的情况是,在第一个参数之后,以下参数被写入到现在被 'elem' 引用的某个其他元素。
我还要提一下,这似乎只有在我调用这个函数后直接写东西时才会发生,像这样:
div.writeInSteps("This", " is", " not", " working");
$id("body").innerHTML += "Doh!";
如果我在调用这个函数后不写任何东西,它似乎工作正常。
如果我将上面的代码改为:
HTMLElement.prototype.writeInSteps = function() {
var i = 0;
var e = this.id;
var args = arguments;
function step() {
var elem = $id(e);
elem.innerHTML += args[i];
if(i < args.length) {
i += 1;
} else {
elem.innerHTML = "";
i = 0;
}
setTimeout(step, 500);
}
step();
}
一切都是花花公子。我的问题是,第一个版本的幕后究竟发生了什么?
编辑:根据ntownsend 的要求,更新了有关“...直接在...之后写一些东西”和浏览器使用情况的请求详细信息。 Bryan Matthews,我不知道如何提供一个测试页面而不会使这个问题过于混乱。
【问题讨论】:
-
你应该在修改后的版本中将
elem设为局部变量;现在它是一个隐式全局变量,如果你不小心,很容易导致奇怪的错误(如果你不必担心,为什么要担心呢?)。 -
您能否提供一个示例页面来演示此行为?我试用了您的第一个版本,它似乎工作得很好,包括同时执行多个。
-
杰夫是对的。虽然我确信这只是一个重构错误。
-
你能澄清一下“这似乎只发生在我调用函数后直接写东西时”的意思吗?您的意思是,如果在调用
writeInSteps之后,您尝试更改您正在调用该函数的 HTMLElement 的内容,那么您只会看到奇怪的行为?另外,你是怎么调用函数的? -
另外,这发生在什么浏览器中?我似乎无法重现它。
标签: javascript reference closures