Javascript:函数中的变量重新声明导致未定义

时间:2015-07-12 02:58:44

标签: javascript scope hoisting

为什么console.log(foo)在< - p>中产生undefined而不是'bar'

var foo = 'bar';
(function() {
    console.log(foo);
    if(foo === 'baz') {
        var foo = 'qux';
    }
})();

- 如果'bar'替换为var foo,则生成foo?我知道重新声明变量是不好的做法,但var foo = 'qux'永远不会被评估,即使它是,它仍然不应该做任何事情,对吧?

JSFiddle

1 个答案:

答案 0 :(得分:1)

Javascript&#34; hoists&#34;变量声明,意味着稍后在代码中出现的变量声明是&#34;悬挂&#34;到他们包含范围的顶部。这意味着:

(function() {
    console.log(foo);
    if(foo === 'baz') {
        var foo = 'qux'
    }
});

变为:

(function() {
    var foo;
    console.log(foo);
    if(foo === 'baz') {
         foo = 'qux'
    }
}); 

即使重新分配/&#34;重新声明&#34; foo永远不会明确地运行。 Adequately Good总结起来远远超过了充分。

但是,乍一看,我们的示例看起来像是this question的情况。诀窍在于,因为函数具有自己的范围从其包含的范围继承(在本例中是全局范围),所以声明任何变量,即使它存在于继承范围内,也可以保证分配前undefined

我最初想提出这个问题,因为我认为这是setTimeoutclearTimeout的错误,这样的代码经常抛出Cannot set property 'className' of undefined

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

我后来发现var that重新声明是罪魁祸首,经过一些研究后得出的结论是吊装和功能范围是罪魁祸首。不过,我不知道我对范围界定的解释是否完全准确,并且会很感激反馈。