玩命加载中 . . .

JS 之作用域


作用域

是指作用域是指程序源代码中定义变量的区域。

块级作用域

指在代码块 {} 里面定义的变量,只会在当前代码块有效,如果外层作用域下想访问该变量,会报引用错误异常。
使用关键字 letconst 定义块级作用域的变量。

for (let i = 0; i < 10; i++) {}
console.log(i) // ReferenceError: i is not defined

// 因为 i 是用 let 生命的,只能在 let 的作用域里使用,即 for 循环内部有效,外部作用域是访问不到的。

函数作用域

是指包裹在函数里的作用域,其中的变量或者内部函数,对外都是封闭的,即外界无法访问。

function f1() {
    var a = 1;
    var b = 2;
    var c = 3;
}

console.log(a, b, c) // ReferenceError: a, b, c is not defined

全局作用域

是最外层的全局作用域,任何地方都可以访问得到。
在最外层作用域下使用 var 关键字会定义全局变量,也就是说会挂载在 window 对象上,或者不使用关键字 var、let、const 直接对变量名字进行赋值,JS也会自动为其创建为全局变量。

var a = 10;

function f1() {
    b = 20

    function f2() {
        c = 30
        console.log(a) // 10
    }

    f2()
}

f1()

// b 和 c 变量被隐式声明到全局变量了,所以能访问到,这也叫变量提升机制
console.log(b) // 20
console.log(c) // 30

// 但 a,b,c 也被挂载在 window 对象(全局作用域)上面了
console.log(window.a) // 10
console.log(window.b) // 20
console.log(window.c) // 30

词法作用域

在变量定义时决定(也叫静态作用域)。例如函数的作用域是在函数定义时决定的。

动态作用域

在变量调用时才决定。例如函数的作用域是在函数调用的时候才决定的。
基于这两种作用域的不同,于是作用域的嵌套情况也不相同。

下面来看一个案例:

var value = 1;
function foo() {
  console.log(value);
}
function bar() {
  var value = 2;
  foo();
}
bar();

// 结果是???
  • 假设JavaScript采用静态作用域,让我们分析下执行过程:
    • 嵌套情况:全局作用域–>foo函数作用域–>bar函数作用域
    • 于是:执行 foo 函数,先从 foo 函数作用域里查找是否有局部变量 value。如果没有,就根据函数定义的位置,往外一层的作用域里查找变量,发现在全局作用域里找到变量 value ,所以结果会打印 1。
  • 假设JavaScript采用动态作用域,让我们分析下执行过程:
    • 嵌套情况:全局作用域–>bar函数作用域–>foo函数作用域
    • 于是:执行 foo 函数,依然是从 foo 函数作用域里查找是否有局部变量 value。如果没有,就从调用函数的作用域,再往外一层也就是 bar 函数作用域里查找 value 变量,所以结果会打印 2。
  • 由于JavaScript采用的是静态作用域,所以这个例子的结果是 1。

文章作者: hcyety
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hcyety !
评论
  目录