作用域 作用域链 执行上下文

174 阅读3分钟

什么是作用域?

简单来说就是定义变量的区域

全局作用域和局部作用域

全局 JavaScript 变量:在函数外声明的变量和未声明且赋值的变量是全局变量。全局变量会在页面关闭后被删除。在页面中任何地方都能够访问得到的变量,拥有全局的作用域。 局部 JavaScript 变量:在 JavaScript 函数内部声明的变量(使用 var)是局部变量。局部变量会在函数运行以后被删除。 只能在固定的代码片段(函数片段中)中访问到。

在javascript中,if、while、for 等代码块不能形成独立的作用域。

块级作用域

es6.ruanyifeng.com/#docs/let#%…

静态作用域与动态作用域

因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。

而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。

JavaScript采用的是静态作用域

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();//"local scope"

作用域链

每一个Execution Context中都有一个VO,用来存放变量,函数和参数等信息。

在JavaScript代码运行中,所有用到的变量都需要去当前AO/VO中查找,当找不到的时候,就会继续查找上层Execution Context中的AO/VO。这样一级级向上查找的过程,就是所有Execution Context中的AO/VO组成了一个作用域链。

当访问变量时,会从先从当前作用域查找,如果找不到就会从当前作用域一层层向上查找,直到找到或为undefined为止,这种向上查找的链式结构,就是作用域链 。

var data = [];
for(var i = 0 ; i < 3; i++){
    data[i]=function() {
        console.log(i);
    }
}

data[0]();// 3
data[1]();// 3
data[2]();// 3

执行上下文

简单来说, 执行上下文就是Javascript 的执行环境

当javascript执行一段可执行代码的时候时,会创建对应的执行上下文栈

当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。

执行上下文类型

全局执行上下文这是默认或者说是最基础的执行上下文,一个程序中只会存在一个全局上下文,它在整个 javascript 脚本的生命周期内都会存在于执行堆栈的最底部不会被栈弹出销毁。全局上下文会生成一个全局对象(以浏览器环境为例,这个全局对象是 window),并且将 this 值绑定到这个全局对象上。

函数执行上下文每当一个函数被调用时,都会创建一个新的函数执行上下文(不管这个函数是不是被重复调用的)

Eval 函数执行上下文 执行在 eval 函数内部的代码也会有它属于自己的执行上下文,但由于并不经常使用 eval,所以在这里不做分析。 1.根据函数的参数,创建并初始化arguments object。

2.扫描上下文的函数声明:对于找到的函数声明,将函数名和函数引用存入VO中,如果VO中已经有同名函数,那么就进行覆盖。

3.扫面上下文的变量声明:对于找到的每个变量声明,将变量名存入VO中,并且将变量的值初始化为undefined。如果变量的名字已经在变量对象里存在,不会进行任何操作并继续扫描。

image.png