Javascript:函数中的变量重新声明导致未定义
为什么Javascript:函数中的变量重新声明导致未定义,javascript,scope,hoisting,Javascript,Scope,Hoisting,为什么console.log(foo)会生成undefined而不是中的'bar'- var foo = 'bar'; (function() { console.log(foo); if(foo === 'baz') { var foo = 'qux'; } })(); -但是如果var foo替换为foo,会产生'bar'?我知道重新声明变量是不好的做法,但无论如何都不会对var foo='qux'进行计算,即使是这样,它也不应该做任何事情,对吗 J
console.log(foo)
会生成undefined
而不是中的'bar'
-
var foo = 'bar';
(function() {
console.log(foo);
if(foo === 'baz') {
var foo = 'qux';
}
})();
-但是如果var foo
替换为foo
,会产生'bar'
?我知道重新声明变量是不好的做法,但无论如何都不会对var foo='qux'
进行计算,即使是这样,它也不应该做任何事情,对吗
Javascript“提升”变量声明,这意味着代码中稍后出现的变量声明被“提升”到其包含范围的顶部。这意味着:
(function() {
console.log(foo);
if(foo === 'baz') {
var foo = 'qux'
}
});
变成:
(function() {
var foo;
console.log(foo);
if(foo === 'baz') {
foo = 'qux'
}
});
即使foo
的重新分配/重新声明从未显式运行。对提升的总结远远不够充分
然而,乍一看,我们的示例看起来像一个例子。诀窍在于,由于函数从其包含作用域(在本例中为全局作用域)继承了自己的作用域,因此声明任何变量(即使它存在于继承的作用域中)都保证在赋值之前未定义
我最初想提出这个问题,因为我认为这是setTimeout
和cleartimout
的错误,像这样的代码不断抛出无法设置未定义的属性“className”:
var timer;
document.getElementById('ele').addEventListener('mousewheel', function() {
var that = this;
clearTimeout(timer);
timer = setTimeout(function() {
that.className = 'foo';
if(false) { //this condition shouldn't have ever been true in my test cases
var that = document.getElementById('otherEle');
setTimeout(function() { /* Things to do with otherEle in 1s */ }, 1000);
}
}, 200);
}, false);
后来我发现,重新声明的变量是罪魁祸首,经过一些研究,我得出结论,吊装和功能范围界定是罪魁祸首。不过,我不知道我对范围界定的解释是否完全准确,我希望得到反馈。你的解释是正确的。一些程序员在其作用域的顶部声明所有变量,以帮助避免类似这样的问题(或者在您的例子中,即
)。