我有一段javascript代码,我在“秘密的JavaScript忍者”(John Resig一书)中找到了这段代码。我有一个问题需要理解变量的行为。 以下是代码(相对于原始代码简化):
(function() {
var results;
this.assert = function assert() {
var li = document.createElement("li");
results.appendChild(li);
return li;
};
this.test = function test(name, fn) {
results = document.getElementById("results");
results = assert().appendChild(document.createElement("ul"));
fn();
};
})();
window.onload = function() {
test("A test.", function() {
assert();
assert();
});
};
我的问题是结果变量。当您输入“测试”功能时,结果变量将首先取值“ul#results”,然后取值“ul”,作为< strong> appendChild 功能。但是当你输入“fn()”函数时,“结果”的值仍然是“ul#results”。为什么?我有一些难以理解的变量范围。
有人可以帮我理解这个话题吗?
非常感谢。
答案 0 :(得分:2)
该变量是在匿名函数的范围内创建的。 assert
和test
都可以访问相同的 results
变量。
答案 1 :(得分:0)
这可能比任何事情都更令人困惑,但基本上代码是递归地将一些子元素添加到DOM中的元素。这是因为变量&#34;结果&#34;在闭包中定义。该变量在该范围内仍然存在。
BTW,这篇文章展示了一些解释javascript变量范围的测试。请记住,它不会像你在这里那样谈论闭包。但它可能有助于解释您遇到的其他一些事情。http://www.computerhowtoguy.com/an-introduction-to-javascript-variable-scope/
这是一步一步解释的过程:
DOM结构在这一点上看起来像这样:
<div id="results">
<li>
<ul>
<li></li>
</ul>
</li>
</div>
所以代码继续发生同样的事情......
这是修改过的代码,现在带有注释:
// the following is a closure. a sort of isolated container with its own scope.
(function() {
// results is not globally scoped, only scoped at the closure level,
// since its defined with "var".
var results;
// "this" is the calling object. (ie: window object)
this.assert = function assert() {
// since "var" is used "li" is part of this function.
var li = document.createElement("li");
// results (at the closure level) appends a child at this function's level.
results.appendChild(li);
// return a javascript reference to the new DOM element.
return li;
};
// again "this" is the calling object. when called in onload below, "this" is the window object.
this.test = function test(name, fn) {
// results refers to the closure level results variable, since var is ommitted.
// this is a reference to an element in the DOM.
results = document.getElementById("results");
// changing the variable now. the DOM object "results" is NOT altered by this assignment, since
// javascript is separate from the DOM.
// NOTE: the assert function was previously assigned to the window object previously. so stuff in that
// function will be window scoped.
results = assert().appendChild(document.createElement("ul"));
// call fn
fn();
};
})();
window.onload = function() {
// at this point, "this" is the "window" object.
// "test" is part of the closure above. in the closure the test function is assigned
// to "this". since we are calling the function here, "this" will be the window object in the
// closure for this call.
test("A test.",
// an anonymous function. this is really just an object passed into the "test" function
function() {
assert();
assert();
}
);
};