JS 调用栈

JS 是一门单线程语言

javascript事件循环

1.既然js是单线程,那就像只有一个窗口的银行,客户需要排队一个一个办理业务,同理js任务也要一个一个顺序执行。如果一个任务耗时过长,那么后一个任务也必须等着。那么问题来了,假如我们想浏览新闻,但是新闻包含的超清图片加载很慢,难道我们的网页要一直卡着直到图片完全显示出来?因此聪明的程序员将任务分为两类:同步任务和异步任务

执行上下文

1.执行上下文是评估和执行 JavaScript 代码的环境的抽象概念。每当 Javascript 代码在运行的时候,它都是在执行上下文中运行。
2.类型
    2.1 全局执行上下文 — 这是默认或者说基础的上下文,任何不在函数内部的代码都在全局上下文中。它会执行两件事:创建一个全局的 window 对象(浏览器的情况下),并且设置 this 的值等于这个全局对象。一个程序中只会有一个全局执行上下文。
    2.2 函数执行上下文 — 每当一个函数被调用时, 都会为该函数创建一个新的上下文。每个函数都有它自己的执行上下文,不过是在函数被调用时创建的。函数上下文可以有任意多个。每当一个新的执行上下文被创建,它会按定义的顺序(将在后文讨论)执行一系列步骤。
    2.3 Eval 函数执行上下文 — 执行在 eval 函数内部的代码也会有它属于自己的执行上下文,但由于 JavaScript 开发者并不经常使用 eval,所以在这里我不会讨论它。
3.执行栈(调用栈):
    3.1 当 JavaScript 引擎第一次遇到你的脚本时,它会创建一个全局的执行上下文并且压入当前执行栈。每当引擎遇到一个函数调用,它会为该函数创建一个新的执行上下文并压入栈的顶部。
    3.2 引擎会执行那些执行上下文位于栈顶的函数。当该函数执行结束时,执行上下文从栈中弹出,控制流程到达当前栈中的下一个上下文。
4.怎么创建执行上下文
    4.1 创建执行上下文有两个阶段:1) 创建阶段 和 2) 执行阶段。
    4.2 创建阶段会发生三件事:
        4.2.1 this 值的决定,即我们所熟知的 This 绑定。
            4.2.1.1 在全局执行上下文中,this 的值指向全局对象。(在浏览器中,this引用 Window 对象)。
            4.2.1.2 在函数执行上下文中,this 的值取决于该函数是如何被调用的。如果它被一个引用对象调用,那么 this 会被设置成那个对象,否则 this 的值被设置为全局对象或者 undefined(在严格模式下)
               function A(){
                    b:function(){
                        console.log(this);
                    }
                }
                A.b();//{b:f},this引用的是A,因为b在A中被调用
                var b=A.b;
                b();//windowd对象,this指向的是全局对象window,因为没有指向引用对象

 

        4.2.2 创建词法环境组件。
            4.2.2.1 官方的 ES6 文档把词法环境定义为:词法环境是一种规范类型,基于 ECMAScript 代码的词法嵌套结构来定义标识符和具体变量和函数的关联。一个词法环境由环境记录器和一个可能的引用外部词法环境的空值组成。简单来说词法环境是一种持有标识符—变量映射的结构。(这里的标识符指的是变量/函数的名字,而变量是对实际对象[包含函数类型对象]或原始数据的引用)。
            4.2.2.2 在词法环境的内部有两个组件:(1) 环境记录器和 (2) 一个外部环境的引用。
                a 环境记录器:存储变量和函数声明的实际位置。
                    类型 1.声明式环境记录器存储变量、函数和参数。
                         2.对象环境记录器用来定义出现在全局上下文中的变量和函数的关系。
                b 外部环境的引用意味着它可以访问其父级词法环境(作用域)。
            4.2.2.3 类型:
                a 全局环境(在全局执行上下文中)是没有外部环境引用的词法环境。全局环境的外部环境引用是 null。它拥有内建的 Object/Array/等、在环境记录器内的原型函数(关联全局对象,比如 window 对象)还有任何用户定义的全局变量,并且 this的值指向全局对象。
                b 在函数环境中,函数内部用户定义的变量存储在环境记录器中。并且引用的外部环境可能是全局环境,或者任何包含此内部函数的外部函数。
                c 在全局环境中,环境记录器是对象环境记录器;在函数环境中,环境记录器是声明式环境记录器。对于函数环境,声明式环境记录器还包含了一个传递给函数的 arguments 对象(此对象存储索引和参数的映射)和传递给函数的参数的 length。
        4.2.3 创建变量环境组件。
            4.2.3.1 它同样是一个词法环境,其环境记录器持有变量声明语句在执行上下文中创建的绑定关系。所以它有着上面定义的词法环境的所有属性。在 ES6 中,词法环境组件和变量环境的一个不同就是前者被用来存储函数声明和变量(let 和 const)绑定,而后者只用来存储 var 变量绑定。
        ExecutionContext = {
            ThisBinding = <this value>,
            LexicalEnvironment = { ... },
            VariableEnvironment = { ... },
        }

调用栈

0.前置说明:
    0.1 JavaScript 是一门单线程的语言,这意味着它只有一个调用栈,因此,它同一时间只能做一件事。
    0.2 内存堆:这是内存分配发生的地方.
    0.3 调用栈:这是你的代码执行时的地方
1.定义:调用栈是解释器(就像浏览器中的javascript解释器)追踪函数执行流的一种机制。当执行环境中调用了多个函数时,通过这种机制,我们能够追踪到哪个函数正在执行,执行的函数体中又调用了哪个函数。
    1.1 每调用一个函数,解释器就会把该函数添加进调用栈并开始执行。
    1.2 正在调用栈中执行的函数还调用了其它函数,那么新函数也将会被添加进调用栈,一旦这个函数被调用,便会立即执行。
    1.3 当前函数执行完毕后,解释器将其清出调用栈,继续执行当前执行环境下的剩余的代码。
    1.4 当分配的调用栈空间被占满时,会引发“堆栈溢出”。
2.例子:
function Hello(){
        var a=1;
        hi();
        b=1;
    }
    function hi(){
        var c=1;
    }
    Hello();

  

  2.1 hello函数被调用,将Hello添加进调用栈表 
  2.2 执行Hello中的所有代码
  2.3 直到执行hi,将hi添加进调用栈
2.4 执行hi的所有代码,一直到执行完毕
2.5 删除调用栈中的hi
2.6 继续执行hello后面的代码,执行到完毕
2.7 删除调用栈中的hello


 

 

转载于:https://www.cnblogs.com/shuajing/p/10800656.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值