JavaScript 执行上下文和作用域链

执行上下文

执行上下文决定了变量和函数可以访问哪些数据。

一个执行上下文就对应一个仅后台可访问的变量对象,其中保存有该上下文的局部变量、参数和函数声明。

最外层的上下文称为全局上下文。宿主环境不同,全局上下文的关联对象就不同。在浏览器中,全局上下文就是window 对象。

注意window后没有s

除了 window 对象自带的属性外,使用var定义的全局变量和函数都会成为其属性。

var具有函数作用域,let和const具有块级作用域

var a1=1;
function func(){
    var a2=2;
}
console.log(a1); //输出1
console.log(typeof a2 === "undefined"); //输出true
console.log(window.a1); //输出1

window.a1也可以写成window['a1']

一般的上下文在其代码执行完后就销毁,而全局上下文是在程序退出时才被销毁。

执行上下文会按照函数的调用顺序形成一个堆栈,称为执行上下文栈

当前执行上下文位于执行上下文栈的顶端,当它执行完后会被弹出,程序的控制权就交给之前的上下文。

我们用到的、见到的this指针指向的就是这个当前执行上下文,其值取决于函数的调用方式。

作用域链

作用域链(scope chain)决定了变量和函数的访问权限和顺序,这个链的最前端是当前执行上下文的变量对象。

作用域链的先后顺序就是内外顺序,内部执行上下文包含了外部执行上下文。换句话说,内部执行上下文可以访问外部执行上下文。

我们访问变量和函数的顺序就是从作用域链的前面往后面找。

看个例子:

const a4=4;
var a5=5;
const func1 = function (a3) {
    const a2=2;
    function func2() {
        const a1=1;
        return function func3(){
            console.log(a1+a2+a3+a4+a5);
        }
    };
    return func2();
};
const result=func1(3);
result();

JavaScript 执行上下文和作用域链_第1张图片

[[Scopes]]记录的是变量的父作用域链,可以看到result并没有func3的上下文。


作用域链增强

有两个影响作用域链的行为:withtry/catch的catch块

使用with将指定对象的作用域推入上下文栈:

let person={
    name:'Carl',
    age:22
}
with(person){
    console.log(name+"'s age is "+age);
}

try/catch语句的catch块是一个单独的上下文,捕获的错误信息被添加到catch块的变量对象上,于是只能在catch块才能访问该错误。

你可能感兴趣的:(JavaScript,javascript)