执行上下文与作用域

233 阅读2分钟

全局执行上下文

  1. 在执行全局代码之前将window确定为全局执行上下文;
  2. 对全局数据进行预处理
    • var定义的全局属性 ==> undefined,添加为window属性
    • function声明的全局函数 ==> 赋值,添加为window方法
  3. 开始执行全局代码

函数执行上下文

  1. 在调用函数,准备执行函数体前,创建相应的函数执行上下文对象
  2. 对局部数据进行预处理
    • 形参变量 ==> 赋值(实参) ==> 添加为函数执行上下文属性
    • arguments ==>赋值(实参列表) ==> 添加为函数执行上下文属性
    • var定义的局部属性 ==> undefined,添加为函数执行上下文属性
    • function声明的函数 ==> 赋值,添加为函数执行上下文方法
    • this ==> 赋值(调用函数的对象) ==>添加为函数执行上下文属性
  3. 开始执行函数体代码

执行上下文栈

  1. 在全局代码执行前,js引擎会创建一个栈来存放执行上下文对象;
  2. 在全局执行上下文(window)确定后,将其压入栈底;
  3. 在函数执行上下文创建后,将其压入栈中;
  4. 在当前函数执行完成后,将栈顶对象弹出;
  5. 在所有函数执行都执行完后,将全局执行上下文对象从栈顶弹出

作用域

  1. 编写代码时确定的一块静态代码段所在区域,主要分为全局作用域和函数作用域
  2. ES6之前没有块级作用域,es6之后新增了块级作用域
  3. 作用:用于隔离变量,防止不同作用于下的同名变量造成冲突

作用域与执行上下文的区别

  1. 区别1:
    • 全局作用域之外,每个函数都会创建自己的作用域,作用域在定义函数时就确定了,而不是在调用是确定的;
    • 全局执行上下文是在全局作用域确定后,JS代码马上执行前创建的;
    • 函数执行上下文是在调用函数时,函数体执行之前创建的。
  2. 区别2:
    • 作用域是静态的,只要函数定义好就一直存在,且不会改变;
    • 上下文环境是动态的,调用函数时创建,函数调用结束后就会被释放。

联系

  1. 执行上下文从属于所在的作用域。
  2. 全局执行上下文 ==> 全局作用域
  3. 函数执行上下文 ==> 函数作用域

面试题

var x = 10 
function fn(){
  console.log(x)
}

function show(f){
  var x = 20
  f()
}

show(fn)   //10 

var fn = function(){
  console.log(fn)
}
fn()  //function fn(){}

var  obj = {
    fn2:function(){
        console.log(fn2)       //报错 fn2 is not defind
    //  console.log(this.fn2)   //function(){...}

    }
}
obj.fn2()  //报错 fn2 is not defind