zoukankan      html  css  js  c++  java
  • js 执行上下文

    前言

    什么执行上下文?

    就是当前代码将会在什么样的环境运行。

    执行上下文分为3类:

    1.全局执行上下文,在全局中的上下文

    2.函数执行上下文,在函数中的上下文

    3.Eval函数执行上下文,很少使用。如果安全最好使用Function。

    全局执行上下文:

    这是默认的、最基础的执行上下文。不在任何函数中的代码都位于全局执行上下文中。
    
    它做了两件事:
    
    1. 创建一个全局对象,在浏览器中这个全局对象就是 window 对象。
    
    2. 将 this 指针指向这个全局对象。一个程序中只能存在一个全局执行上下文。
    

    在此就不过多介绍全局执行上下文,主要介绍函数执行上下文。

    函数执行上下文

    每一个函数执行的时候都会有一个执行前,都会有一个函数执行上下文,那么是如何管理的呢?

    有一個執行上下文棧:

    其实上面这个图不准确。

    看到图的main,也就是栈的最底层。显示的应该是globalContext.

    执行console.log的时候log的上下文进栈,当要执行bar的时候,bar的上下文进栈,然后far上下文进栈,当far执行完毕,far的上下文出栈。

    这样做的好处就是,当执行代码的时候,只要取栈顶,那么得到的就是当前上下文执行的栈。

    执行上下文的生命周期:

    创建阶段 → 执行阶段 → 回收阶段

    创建阶段

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

    1.创建变量对象:首先初始化函数的参数 arguments,提升函数声明和变量声明。下文会详细说明。

    2.创建作用域链(Scope Chain):在执行期上下文的创建阶段,作用域链是在变量对象之后创建的。

    作用域链本身包含变量对象。作用域链用于解析变量。

    3.当被要求解析变量时,JavaScript 始终从代码嵌套的最内层开始,如果最内层没有找到变量,就会跳转到上一层父作用域中查找,直到找到该变量。

    确定 this 指向

    先来看下变量对象:

    1. 变量声明提升
    console.log(a); // undefined
    var a = 10;
    

    简单点就是说,在程序运行之前扫码一遍,把变量进树。然后赋值undefine.

    2.函数声明提升

    在程序运行之前扫码一遍,把函数进树,注意是将函数对象进树,此时是会实例化的。

    注意事项:

    当函数申明提示和变量声明提升 冲突的时候,那么函数申明为主
    

    3.确定this

    直接给图看哈。

    作用域链:

    什么是作用域链?是这样子的。

    我们发现有一个问题,那就是我们可以访问全局变量,这神奇吗?

    可能有些人觉得,这有什么?我们的思维已经固定了,认为不就是访问全局变量吗。

    它的实现是这样子的:

    上下文时候有一个[[scope]],存储的是上级上下文的变量对象。

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

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

    那么这时候可以回顾一下上下文是如何创建的。

    先创建上下文对象,假如checkscope的上下文,我命名为checkscopeContext

    1.checkscope 函数被创建,保存作用域链到 内部属性[[scope]]

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

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

    ECStack = [
    checkscopeContext,
    globalContext
    ];

    3.checkscope 函数并不立刻执行,开始做准备工作,第一步:复制函数[[scope]]属性创建作用域链

    checkscopeContext = {
    Scope: checkscope.[[scope]],
    }

    4.第二步:用 arguments 创建活动对象,随后初始化活动对象,加入形参、函数声明、变量声明

    checkscopeContext = {
    AO: {
    arguments: {
    length: 0
    },
    scope2: undefined
    },
    Scope: checkscope.[[scope]],
    }

    5.第三步:将活动对象压入 checkscope 作用域链顶端

    checkscopeContext = {
    AO: {
    arguments: {
    length: 0
    },
    scope2: undefined
    },
    Scope: [AO, [[Scope]]]
    }
    后面进入执行步骤,当函数执行完毕弹出。

  • 相关阅读:
    大文件处理
    查看系统声卡信息
    C# 禁止程序多个实例运行
    C#绘制传感器代码
    Arcgis 属性表模糊查询
    Python筛选Excel列数据,并导出!
    c#实现:返回n到m之间的所有素数
    C# 判断一个整数是否是素数!使用bool IsPrim(int n)实现!
    打开Arcgis,ArcToolbox却打不开,还闪退!!!
    AE常用功能
  • 原文地址:https://www.cnblogs.com/aoximin/p/12460228.html
Copyright © 2011-2022 走看看