2018-01-07 执行上下文相关

scope

函数在创建时,会添加[[scope]]属性

var x = 3
function parent(){
var x = 4
  function kid(){
   var x = 5
  }
}

parent的[[scope]] = [globalContext.VO]
kid的[[scope]] = [parentConetext.AO,globalContext.VO]

执行上下文 execution context

  • 在运行代码时,首先会创建一个执行上下文栈,假设是一个数组ECStack = [ ].
    当javascript执行代码时,首先遇到的是全局执行上下文,所以此时ECStack = [ globalContext ]
    只有当程序运行结束时,ECStack才会被清空,否则globalContext会一直在栈底.

  • 每当有一个函数运行,就将该函数的执行上下文压人该栈,运行结束时弹出.全局上下文始终在栈尾.

function fun3() {
    console.log('fun3')
}

function fun2() {
    fun3();
}

function fun1() {
    fun2();
}

fun1();

伪代码:

// fun1()
ECStack.push(<fun1> functionContext);

// fun1中竟然调用了fun2,还要创建fun2的执行上下文
ECStack.push(<fun2> functionContext);

// 擦,fun2还调用了fun3!
ECStack.push(<fun3> functionContext);

// fun3执行完毕
ECStack.pop();

// fun2执行完毕
ECStack.pop();

// fun1执行完毕
ECStack.pop();

// javascript接着执行下面的代码,但是ECStack底层永远有个globalContext

  • 当函数运行时,会创建一个执行上下文,有this,scope,变量对象三个属性

1. 变量对象(varialbe object)

变量对象是与执行上下文的数据作用域,存储了在上下文中定义的变量和函数声明.

function foo(a) {
  var b = 2;
  function c() {}
  var d = function() {};

  b = 3;

}

foo(1);

运行代码至foo(1),时创建该函数的执行上下文,其中的变量对象为

AO = {
  arguments: {
    0: 1,
  lenght: 1
  },
 a: 1,
 b: 3,
 c: function(){},
 d: reference to FunctionExpression "d"
}

2. 作用域链 scope chain

当函数激活时,将活动对象添加到作用域链的前端
Scope = [AO].concat([[scope]])

3. this

流程图/总结

var scope = "global scope";
function checkscope(){
    var scope2 = 'local scope';
    return scope2;
}
checkscope();

执行过程如下:

  1. checkscope 函数被创建,创建内部属性[[scope]]
checkscope.[[scope]] = [
    globalContext.VO
];
  1. 执行 checkscope 函数,创建 checkscope 函数执行上下文,checkscope 函数执行上下文被压入执行上下文栈
ECStack = [
    checkscopeContext,
    globalContext
];
  1. checkscope 函数并不立刻执行,开始做准备工作,第一步:复制函数[[scope]]属性创建作用域链
checkscopeContext = {
    Scope: checkscope.[[scope]],
}
  1. 第二步:用 arguments 创建活动对象,随后初始化活动对象,加入形参、函数声明、变量声明
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: undefined
    }
}
  1. 第三步:将活动对象压入 checkscope 作用域链顶端
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: undefined
    },
    Scope: [AO, [[Scope]]]
}
  1. 准备工作做完,开始执行函数,随着函数的执行,修改 AO 的属性值
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: 'local scope'
    },
    Scope: [AO, [[Scope]]]
}
  1. 查找到 scope2 的值,返回后函数执行完毕,函数上下文从执行上下文栈中弹出
ECStack = [
    globalContext
];

原文: https://juejin.im/post/59278e312f301e006c2e1510

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容