ECMAScript作用域与作用域链

Posted goodfeeling

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ECMAScript作用域与作用域链相关的知识,希望对你有一定的参考价值。

  执行环境(execution context,我们也叫做“环境”)是定义变量和函数有权访问的其他数据的重要概念,在javascript中它决定了各自的行为,在每个执行环境中与之关联的变量对象(vanriable object),环境中定义的所有变量和函数都保存在这个变量中,解析器会在后台处理数据是使用这个对象。

 

一、变量的声明

我们可以声明全局变量和局部变量,直接使用var声明一个变量,该变量会自动被添加到最近的环境中:

function sum(a1, a2) {
    var enter = a1 + a2;
    return enter;
}
var result = sum(20,30);//50
console.log(enter);//报错

如果初始化变量式没有使用var声明,该变量会自动被添加到全局环境:

function sum(a1, a2) {
    all = a1 + a2;
    return all;
}
var result = sum(20,30);//50
console.log(all);//50

注意:在严格模式下,初始化未经声明的变量会导致错误。

 

二、变量作用域

  打开Google Chrome浏览器开发工具Developer Tools,快捷键(ctrl + shift + J):

var global = "window";
function area() {
    var enter = "thisArea";//局部变量在函数执行结束时会被销毁
    console.log("输出" + global);//访问全局变量global
}
area();
console.log(enter);//输出错误

技术分享图片

  在全局执行环境是最外围的一个执行环境,在web浏览器中,全局执行环境被认为是window对象,所以说,全局变量和函数都时作为window对象的属性和方法创建的。某个执行环境中的所有代码执行完毕会被销毁,其中保存的变量和参数定义也随之销毁。

 

三、作用域链

  当你要执行一段代码时,会创建变量对象的一个作用域链(scope chain),作用域链可以保证对执行环境有权访问的所有变量和函数的有序访问。在作用域链前端,始终都是当前执行的代码所在环境的变量对象。而如果时环境是函数,则将其活动对象作为变量对象,这个活动对象开始时只包含一个变量,即arguments对象。对每个包含环境往上搜索,一直到全局执行环境,它作为最后一个对象。

  标识符解析式沿着作用域链递进往上搜索,搜索过程开始在作用域链前端开始,一直追溯到全局环境的变量对象,如果在全局环境没有找打这个标识符,则这会被认为该变量未声明,而会导致输出错误:

var temper = 38;
function changTemper() {
    if (temper > 37){
        console.log("Your temperature is too high.");
    }else if(temper = 37) {
        console.log("Your body temperature is normal.");
    }else{
        console.log("Your body temperature is too low.");
    }
}
changTemper();//Your temperature is too high.

函数内部可以访问外部环境的变量,它们是通过作用域链来查找该变量的,如果途中找到该变量,就会停止终止查找。

还有就是,局部作用域中定义的变量可以在外部环境中域全局变量互换使用。

var global = 1;
function area1() {
    var thisOne = 2;
    
    function area2() {
        var thisTwo = thisOne;
        thisOne = global;
        global = thisTwo;
        var thisTwo = arae;//报错
        /*
        能访问到的说明外部有,或者本函数有这个变量。
        thisTwo需要访问外部变量的时候它会一级一级往上搜索
        如果没有搜索到,就会报错。
        */
    }
    area2();
}
area1();

技术分享图片

 

 

 

四、延长作用域链

  执行环境的类型总共有两种——全局和局部函数,但还是有其他办法来延长作用域链。有一些语句能够前作用域链前端临时增加一个变量对象,该变量对象会在代码执行后被移除,具体来说,就是当执行流进入下列任何语句式,作用域链就会得到加长:

  with语句

这个语句将会指定的对象添加到作用域链中。with语句可以接收location对象,在location对象中包含了所有的属性和方法,这个变量对象被添加到了作用域链的前端。当在with语句中引用变量href式,可以在执行环境中找到。在with语句内部,定义了一个名为url的变量,因而url就成了函数执行环境的一部分。

function create() {
    var de = "?debug=true";
    with(location){
        var url = href + de;
    }
    return url;//
}

 

 总结:

  1. 执行环境决定了变量的生命周期;
  2. 执行环境有全局执行环境和函数执行环境之分;
  3. 每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链;
  4. 函数的局部环境有权访问函数的作用域中的变量,还可以有权访问其包含(父)环境;
  5. 全局环境只能访问在全局环境中定义的变量,不能直接访问局部环境中的任何数据;

 如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果您喜欢或者有所启发,欢迎添加收藏,一起加油学习啊。

以上是关于ECMAScript作用域与作用域链的主要内容,如果未能解决你的问题,请参考以下文章

作用域与作用域链

作用域与作用域链

Js作用域与作用域链详解

js函数3-作用域与作用域链

JavaScript-作用域与作用域链

JavaScript的作用域与作用域链