JavaScript变量未定义

10

首先,让我们看看代码。

var a=0;
b=1;
document.write(a);
function run(){
    document.write(b);
    var b=1;
}
run();

我认为结果应该是01,但实际上,结果是0undefined

然后我修改了这段代码。

var a=0;
b=1;
document.write(a);
function run(){
    document.write(this.b); //or document.write(window.b)
    var b=1;
}
run();

是的,这次它按照预期运行了。 01。我不明白,为什么呢?

更有趣的是,我又修改了代码。

var a=0;
b=1;
document.write(a);
function run(){
    document.write(b);
    //var b=1;       //I comment this line
}
run();

结果是01。

那么,有人能解释一下吗?

感谢分享你的观点。 我简化了这段代码。

b=1;
function run(){
    console.log(b); //1
}

二:

b=1;
function run(){
    var b=2;
    console.log(b); //2
}

三:

b=1;
function run(){
    console.log(b); //undefined
    var b=2;
}

注意,我最初读这个问题的方式是你想知道为什么 this.b(以及 window.b)有效,但是在函数中的 var b... 之前,只有简单的 b 是无效的。在那种情况下,thiswindow 是相同的。如果你看过使用函数和局部作用域创建的对象,这可能会让人感到困惑,但这是因为函数可以被用作构造函数。此外,var 声明“升起”到执行之前的作用域顶部的效果被称为变量提升。这就是为什么 var b... 是局部的原因。 - Jared Farrish
请查看我的评论:http://jsfiddle.net/userdude/NMxdU/6/ 你需要打开控制台,比如说Firebug或者Chrome控制台。 - Jared Farrish
4个回答

18

当你在函数中引用变量时,JS首先会查找该变量是否在当前作用域内声明,即在该函数内部。如果未找到,则会查找包含该函数的作用域。如果仍未找到,则会查找上一个作用域,直到最终达到全局作用域。(请记住,您可以将函数嵌套在彼此中,这就是您获得多个包含作用域级别的方式,尽管您的示例当然不会这样做。)

下面是陈述:

b=1;

without var声明的变量是全局变量,在任何函数中都可以访问,但在第一个函数中你也声明了一个本地变量b,这被称为变量屏蔽

但是,您可能会说,“我在document.write(b)之后声明了本地变量b”。这里涉及到了声明的“提升”。在函数中声明的变量会被JS解释器视为已经在函数顶部声明(即它被“提升”到顶部),但是任何值分配都发生在原处。因此,实际上会将您的第一个函数执行为:

function run(){
    var b;              // defaults to undefined
    document.write(b);  // write value of local b
    b=1;                // set value of local b
}
在您的第二个函数中,当您使用 this.b 时,您会发现 this 指向 window,全局变量本质上是 window 的属性。因此,您正在访问全局的 b 并忽略了本地的一个。
在您的第三个函数中,您根本没有声明本地 b,因此它引用全局变量。

1
提升:http://bonsaiden.github.com/JavaScript-Garden/#function.scopes - Jared Farrish

3

var指令在预执行阶段进行处理,在document.write(b);之前,b变成局部变量,因此此时bundefined

注意:将值赋给变量是在执行时进行的,因此你可以想象你的代码如下所示。

function run(){
    document.write(b);
    var b=1;
}

与以下代码等效:

function run(){
    var b;
    document.write(b);
    b=1;
}

补充:

这就是为什么将每个变量定义都放在函数顶部是一个很好的习惯。


@JaredFarrish 在那个函数中,thiswindow,而 window['b'] 是全局的 b - xdazz
在这种情况下,答案是提升 - Jared Farrish
1
"带有this的代码非常清晰,不需要回答。" - 对于回答过的人来说很清楚,但我不知道对于提问者是否清楚,而且后来看到这个问题的其他人可能也不清楚。鉴于问题归结为“哪个b是哪个?”一些人可能会认为this.b是指局部变量b,特别是因为局部变量和全局变量都设置为1 - nnnnnn

3
当您编写 b = 1 时,您正在创建全局对象中的属性。
在普通函数中, b 将指向全局对象。

由于您的函数包含 var b; ,因此函数内部的 b 引用本地变量。 ( var 语句会在整个函数中创建局部变量,无论 var 出现在何处)。
然而,可执行的 var 语句部分( b=1 )仅在该点执行。


1
但是至关重要的是,即使 var b = 1; 出现在 document.write() 之后,var b 仍在函数的上下文中定义,直到稍后初始化为 1 才被定义。 - Michael Berkowski
似乎这并没有回答提问者的问题。 - xdazz

0

这段代码对我来说运行良好

  if(var_name === "undefined"){
     alert(var_name+' : undefined');
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接