以下JavaScript范围如何工作

How the below JavaScript Scope works

本问题已经有最佳答案,请猛点这里访问。

我在读有关JavaScript作用域和提升的文章。我看到下面的一个样品,我心里有些疑惑。所以,我想知道它是如何工作的。

1
2
3
4
5
6
7
8
var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

该代码将警告1!但是如果我们消除"function a()"部分,代码将警告10。

那么,它是如何工作的!"函数a()"在这里做什么以及它如何影响作用域。

在这段代码中,我也无法理解空"return"的含义。

那么,这段代码是如何依赖于JavaScript范围工作的呢?


首先,一个"空"的return;语句只是在该点退出函数,返回undefined。相当于return undefined;

简单的情况是,如果去掉function a(){}部分,那么b()函数将全局变量a改为10,那么在运行b()函数后,当您警告a的值时,它就是10。如果没有这个内部函数,所有对a的引用都意味着全局变量。

但对于function a(){}部分,该函数在b()内部声明。它是b()的本地。那么有两个不同的a:全局变量和b()中的局部变量。无论包含函数中出现其他函数语句的位置如何,JS编译器都会将其视为位于函数顶部。因此,即使function a(){}行位于包含b()函数的末尾,实际运行代码时会发生以下情况:

1
2
3
4
5
6
7
8
var a = 1;              // declare a global variable a
function b() {
    function a() {}     // declare a local function a
    a = 10;             // update local a to be 10 instead of a function
    return;
}
b();
alert(a);  // show value of global a, which is still 1


除了nnnnnn伟大的回答之外,我还试图想象一下形势。

使用function a(){}时,代码的行为如下:

1
2
3
4
5
6
7
8
9
10
11
12
scope: window                         scope: b
      |                                   |
      | var a = 1;  //window.a = 1;       |
      |                                   |
      | function b() { -----------------> |
      |                                   | function a(){} // b.a(){} (hoisted to top)
      |                                   | a = 10;        // b.a = 10;
      |                                   | return;
      | } <------------------------------ |
      |                                   |
      | b();                              |
      | alert(a);  // alert(window.a);    |

我们可以看到,function a(){}被提升到函数的顶部,因为它包含一个声明。如果我们删除function a(){},代码的行为如下:

1
2
3
4
5
6
7
8
9
10
11
scope: window                         scope: b
      |                                   |
      | var a = 1;  //window.a = 1;       |
      |                                   |
      | function b() { -----------------> |
      |                                   | a = 10;        // window.a = 10;
      |                                   | return;
      | } <------------------------------ |
      |                                   |
      | b();                              |
      | alert(a);  // alert(window.a);    |


您的代码在功能上与此代码相同:

1
2
3
4
5
6
7
8
var a = 1;
function b() {
    var a = function() {}
    a = 10;
    return;
}
b();
alert(a);

使用function NAME() { ... }符号可以有效地将该函数声明作为本地(到该范围)声明放在当前范围的开头。

实际上,如果你执行

1
2
3
4
5
6
7
8
9
10
var a = 1;
var c= 2;
function b() {
    a()
    a = 10;
    return;
    function a() { alert(c) }
}
b();
alert(a);

它将输出:

1
2
2
1

就我个人而言,我不使用这种符号,我总是明确地使用赋值。

杰西德