对这些问题的最常见的回答是,JavaScript 拥有基于函数的作用域。也就是,你声明的每一个函数都为自己创建了一个气泡,而且没有其他的结构可以创建它们自己的作用域气泡。但是就像我们一会儿将会看到的,这不完全正确。

    但首先,让我们探索一下函数作用域和它的含义。

    考虑这段代码:

    1. function foo(a) {
    2. var b = 2;
    3. // 一些代码
    4. function bar() {
    5. // ...
    6. }
    7. // 更多代码
    8. var c = 3;
    9. }

    在这个代码段中,foo(..) 的作用域气泡包含标识符 abcbar。一个声明出现在作用域 何处无关紧要的,不管怎样,变量和函数属于包含它们的作用域气泡。在下一章中我们将会探索这到底是如何工作的。

    bar(..) 拥有它自己的作用域气泡。全局作用域也一样,它仅含有一个标识符:foo

    因为 abc,和 bar 都属于 foo(..) 的作用域气泡,所以它们在 foo(..) 外部是不可访问的。也就是,接下来的代码都会得到 ReferenceError 错误,因为这些标识符在全局作用域中都不可用:

    1. bar(); // 失败
    2. console.log( a, b, c ); // 3个都失败

    然而,所有这些标识符(abc,和 bar)在 foo(..) 内部 都是可以访问的,而且在 bar(..) 内部也都是可用的(假定在 bar(..) 内部没有遮蔽标识符的声明)。

    函数作用域支持着这样的想法:所有变量都属于函数,而且贯穿整个函数始终都可以使用和重用(而且甚至可以在嵌套的作用域中访问)。这种设计方式可以十分有用,而且肯定可以完全利用 JavaScript 的“动态”性质 —— 变量可以根据需要接受不同种类型的值。

    另一方面,如果你不小心提防,跨越整个作用域存在的变量可能会导致一些意料之外的陷阱。