执行上下文【学习记录】

125 阅读3分钟

js执行的时候,是怎么去执行的呢?代码的执行顺序是怎么样的?执行的这个过程,都发生了什么事情?

问题

请描述一下js在执行代码的过程是怎么样的?

先了解一下作用域

什么叫做作用域?就是变量影响的范围
js使用的是词法作用域,就是静态作用域,函数的作用域在函数定义的时候就决定了。

执行上下文栈

执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。两段代码(冴羽大佬原本例子):

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

//执行上下文栈的变化情况
//ECStack.push(<checkscope> functionContext);
//ECStack.push(<f> functionContext); 
//ECStack.pop(); 
//ECStack.pop();
var scope = "global scope"; 
function checkscope(){ 
    var scope = "local scope"; 
    function f(){ 
        return scope; 
    } 
    return f; 
} 
checkscope()();
//执行上下文栈的变化情况
//ECStack.push(<checkscope> functionContext);
//ECStack.pop(); 
//ECStack.push(<f> functionContext);; 
//ECStack.pop();

这两段代码运行的结果都是一样的,不一样的是,执行上下文栈的变化不一样\

什么是执行上下文

什么是执行上下文?就是当前javaScript代码被解析和执行时存在的环境

当js执行一段代码时,会做一些准备工作,这个准备工作,就是执行上下文。

全局执行上下文(这是默认的,最基础的执行上下文)

  • 不在函数内部的代码都位于全局执行上下文中\
  • 创建一个全局对象,其实就是我们的windown对象\
  • 将this指针指向这个全局对象

函数执行上下文:每次函数被调用的时候,就会创建一个新的执行上下文

  • 每个函数都有自己的执行上下文\
  • 一个程序中可以存在任意数量的函数执行上下文\
  • 每一个函数执行上下文被创建,它都会按照特定的顺序执行一系列的步骤\

执行上下文的生命周期

创建阶段

当函数被调用,但是未执行内部任何代码之前,会做以下几件事:

  • 创建变量对象:首先会初始化函数的参数arguments,提升函数声明和变量声明\
  • 创建作用域链:作用域链在变量对象之后创建,它本身包含变量对象。它是用来解析变量\
  • 确定this指向

执行阶段

执行变量赋值、代码执行。

回收阶段

执行上下文出栈,等待虚拟机回收

描述js执行的过程

        s()
        console.log(s);
        var s = '我是变量'
        function s() {
            console.log('函数执行');
        }
        console.log(s);
        s()
        //因为一开始,是处在于全局作用域下的,所以,全局执行上下文首先进执行上下文栈
        //ECStack.push(windowContext)
        //然后变量提升
        //var s;
        //接着函数提升
        //function s() {
            //console.log('函数执行');
        //}
        //执行s()
        //ECStack.push(S_Context),创建执行上下文,入执行上下文栈
        //执行s函数里面的console.log('函数执行'),输出'函数执行';
        //s函数执行完毕,出栈 ECStack.pop()
        //执行console.log(s),打印s函数
        //执行赋值  s = '我是变量'  ,此时s函数被s的赋值覆盖了
        //执行console.log(s),打印  '我是变量'
        //执行s()  //报错,因为s已经不是一个函数