作用域和作用域链

作用域

定义 : 作用的范围,确定当前执行代码对变量的访问权限
JavaScript采用静态作用域

静态作用域/词法作用域 : 函数作用域在函数定义的时候就已经确定了
动态作用域 : 函数作用域在函数调用时才确定

//静态作用域
var value = 1;
function foo() {
  console.log(value);
}
function bar() {
  var value = 2;
  foo();
}
bar(); //1
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();//local scope
作用域链

定义:当查找变量时,会从当前上下文的变量对象中查找,如果没有找到,就会从父级执行上下文的变量对象中找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象所构成的链表就叫作用域链

定义函数时

函数存在一个内部属性[[scope]],函数被创建时,就会保存所有的父变量对象到其中,不包含本身的变量对象
注意 : [[scope]]不代表完整的作用域链
例子:

function foo() {
    function bar() {
        ...
    }
}
//函数创建时的作用域
foo.[[scope]] = [
  globalContext.VO
];
bar.[[scope]] = [
    fooContext.AO,
    globalContext.VO
];
执行函数时

函数会创建执行上下文,激活变量对象生成活动对象AO,再将AO压入到执行上下文的作用域中

作用域创建完整过程演示
var scope = "global scope";
function checkscope(){
    var scope2 = 'local scope';
    return scope2;
}
checkscope();

1.定义checkscope函数时,保存父级变量对象到内部属性[[scope]]

checkscope.[[scope]] = [
    globalContext.VO
];

2.执行checkscope函数,先创建checkscope函数上下文,将checkscope函数上下文压入到上下文栈

ECStack = [
    checkscopeContext,
    globalContext
];

3.checkscope函数执行上下文的创建阶段

//第一步 : 复制函数[[scope]]的值创建作用域链
checkscopeContext = {
    Scope: checkscope.[[scope]],
}
//第二步 : 用arguments创建活动对象,然后初始化活动对象,加入形参、函数声明、变量声明
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: undefined
    },
    Scope: checkscope.[[scope]],
}
//第三步 : 将活动对象压入checkscope作用域顶端
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: undefined
    },
    Scope: [AO, [[Scope]]]
}

4.checkscope函数代码执行阶段,修改AO的属性值

checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: 'local scope'
    },
    Scope: [AO, [[Scope]]]
}

5.查找到scope2的值,返回后函数执行完毕,函数上下文从执行上下文栈的弹出

ECStack = [
    globalContext
];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值