JavaScript 作用域链

258 阅读2分钟

作用域

个人笔记 - 仅供参考

1. 作用域的产生

在 JavaScript 中, 作用域为可访问变量、对象、函数的集合;
隔离变量:在不同作用域中同名变量不会冲突;

2. 作用域和执行上下文

区别:\underline{区别:}
全局作用域中,每个函数都会创建自己的作用域。
全局执行上下文环境:是全局作用域确定之后,代码执行之前创建。
函数执行上下文环境:是在调用函数时创建,函数代码执行前创建。
函数作用域是静态的,只要函数定义了就一直存在,且不会发生变化。
执行上下文是动态的,调用函数时创建,函数调用结束后会自动释放。

3. 查找变量规则

在作用域中查找变量的规则:\underline{在作用域中查找变量的规则:}
多个上下级关系的作用域形成的链,查找变量方式是从内到外查找;
在当前作用域的执行上下文中查找,如果没有则依次向上一级的函数作用域执行上下文中查找,直到全局作用域的执行上下文,如果全局作用域中的执行上下文也没有,则会报错!

var b = 'boy';
console.log(b); // 输出 boy
function fighting () {
    console.log(a); // 输出 undefined
    console.log(c); // 输出 undefined
    if(a==='apple'){
        a = 'Alice'
    }else{
        a = 'Ada'
    }
    console.log(a); // 输出 Ada 
    var a = 'Andy'; // 此时变量a赋值为Andy
    middle();
    function middle() {
        console.log(c++); // 由于变量c为undefined,此时输出 NaN
        var c = 100; // 变量c赋值为100
        console.log(++c); // 此时输出 101
        small();
        function small () {console.log(a)} // 输入 Andy
    }
    var c = a = 88; // 此时 c = a = 88; 
    function bottom () {
        console.log(this.b); // 此处的this指向全局,所以输出 boy
        b = 'baby';
        console.log(b); // 输出 baby
    }
    bottom();
}
fighting();
console.log(b); // 输出baby

总结

作用域链的作用是保证执行环境里有权访问的变量和函数是有序的。
作用域链的变量只能向上访问,变量访问到window对象即被终止。
作用域链不允许向下访问。
JS中没有块级作用域,若要形成块级作用域,可通过(function(){})();立即执行的形式实现。

函数作用域内使用的变量,如果是在本组用于找不到定义,会依次向上一级查找,直到找到全局作用域,如果都没有则xxx is not defined。这种一层一层类似锁链的关系,叫作用域链。