278 执行上下文执行上下文栈:变量提升与函数提升,执行上下文,执行上下文栈,全局执行上下文,函数执行上下文,练习题

Posted jianjie

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了278 执行上下文执行上下文栈:变量提升与函数提升,执行上下文,执行上下文栈,全局执行上下文,函数执行上下文,练习题相关的知识,希望对你有一定的参考价值。

  • 变量提升与函数提升
    • 变量提升: 在变量定义语句之前, 就可以访问到这个变量(undefined)
    • 函数提升: 在函数定义语句之前, 就执行该函数
    • 先有变量提升, 再有函数提升

变量声明提升、函数声明提升

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>01_变量声明提升、函数声明提升</title>
</head>

<body>
    <!--
1. 变量声明提升
  * 通过var定义(声明)的变量, 在定义语句之前就可以访问到
  * 值: undefined
2. 函数声明提升
  * 通过function声明的函数, 在之前就可以直接调用
  * 值: 函数定义(对象)
3. 问题: 变量提升和函数提升是如何产生的?
-->
    <script type="text/javascript">
        console.log('-----');  // undefined
        var a = 3

        function fn() {
            console.log(a)
            var a = 4
        }
        fn()

        console.log(b); // undefined  变量提升
        fn2(); // 可调用  函数提升
        // fn3() // 不能调用  变量提升  赋值留在原地

        var b = 3

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

        var fn3 = function() {
            console.log('fn3()')
        }
    </script>
</body>

</html>

  • 理解
    • 执行上下文: 由 js引擎 自动创建的对象, 包含对应作用域中的所有变量属性
    • 执行上下文栈: 用来管理产生的多个执行上下文

技术图片


  • 代码分类(位置):
    • 全局: window
    • 函数: 对程序员来说是透明的
  • 生命周期
    • 全局 : 准备执行全局代码前产生, 当页面刷新/关闭页面时死亡
    • 函数 : 调用函数时产生, 函数执行完时死亡
  • 包含哪些属性:
    • 全局 :
      • 用var定义的全局变量 ==>undefined
      • 使用function声明的函数 ===>function
      • this ===>window
    • 函数
      • 用var定义的局部变量 ==> undefined
      • 使用function声明的函数 ===> function
      • this ===> 调用函数的对象, 如果没有指定就是window
      • 形参变量 ===> 对应实参值
      • arguments ===> 实参列表的伪数组
  • 执行上下文创建和初始化的过程
    • 全局:
      • 在全局代码执行前,最先创建一个全局执行上下文(window)
      • 收集一些全局变量, 并初始化
      • 将这些变量设置为window的属性
    • 函数:
      • 在调用函数时, 在执行函数体之前先创建一个函数执行上下文
      • 收集一些局部变量, 并初始化
      • 将这些变量设置为执行上下文的属性

技术图片

技术图片

技术图片

技术图片


demo:执行上下文

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>02_执行上下文</title>
</head>

<body>
    <!--
1. 代码分类(位置)
  * 全局代码
  * 函数(局部)代码
2. 全局执行上下文
  * 在执行全局代码前将window确定为全局执行上下文
  * 对全局数据进行预处理
    * var定义的全局变量==>undefined, 添加为window的属性
    * function声明的全局函数==>赋值(fun), 添加为window的方法
    * this==>赋值(window)
  * 开始执行全局代码
3. 函数执行上下文
  * 在调用函数, 准备执行函数体之前, 创建对应的函数执行上下文对象(虚拟的, 存在于栈中)
  * 对局部数据进行预处理
    * 形参变量==>赋值(实参)==>添加为执行上下文的属性
    * arguments==>赋值(实参列表), 添加为执行上下文的属性
    * var定义的局部变量==>undefined, 添加为执行上下文的属性
    * function声明的函数 ==>赋值(fun), 添加为执行上下文的方法
    * this==>赋值(调用函数的对象)
  * 开始执行函数体代码
-->
    <script type="text/javascript">
        console.log(a1, window.a1)  // undefined undefined
        window.a2()  // a2()
        console.log(this)  // window

        var a1 = 3

        function a2() {
            console.log('a2()')
        }
        console.log(a1)  // 2
    </script>
</body>

</html>

demo:03_执行上下文栈

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>03_执行上下文栈</title>
</head>
<body>
<!--
1. 在全局代码执行前, JS引擎就会创建一个栈来存储管理所有的执行上下文对象
2. 在全局执行上下文(window)确定后, 将其添加到栈中(压栈) 【window压箱底】
3. 在函数执行上下文创建后, 将其添加到栈中(压栈)
4. 在当前函数执行完后, 将栈顶的对象移除(出栈)
5. 当所有的代码执行完后, 栈中只剩下window
-->
<script type="text/javascript">
  var a = 10
  var bar = function (x) {
    var b = 5
    foo(x + b)
  }
  var foo = function (y) {
    var c = 5
    console.log(a + c + y)
  }
  bar(10)
  // bar(10)
</script>

</body>
</html>

练习题

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>04_执行上下文栈2</title>
</head>

<body>
    <!--
1. 依次输出什么?
  gb: undefined
  fb: 1
  fb: 2
  fb: 3
  fe: 3
  fe: 2
  fe: 1
  ge: 1
2. 整个过程中产生了几个执行上下文?  5
-->
    <script type="text/javascript">
        // 进栈:
        // 出栈:(1)f(4)执行完,f(4)出栈,没有输出; (2)f(4)出栈后,执行f(3)【即foo(i + 1)这行】,执行下面的代码,输出 fe3; (3)同理,f(3)出栈后,执行f(2),输出fe2; (4)f(2)出栈后,执行f(1),输出fe1
        console.log('gb: ' + i)
        var i = 1
        foo(1)

        function foo(i) {
            if (i == 4) {
                return
            }
            console.log('fb:' + i)
            foo(i + 1) //递归调用: 在函数内部调用自己
            console.log('fe:' + i)
        }
        console.log('ge: ' + i)
    </script>
</body>

</html>

技术图片


demo :05_测试题

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>05_测试题</title>
    <link rel="stylesheet" href="xxx.css">
    <style>

    </style>
</head>

<body>
    <script type="text/javascript">
        //  测试题1:  先执行变量提升, 再执行函数提升
        function a() {}
        var a
        console.log(typeof a) // 'function'


        //  测试题2:
        if (!(b in window)) {
            var b = 1
        }
        console.log(b) // undefined


        //  测试题3:
        var c = 1

        function c(c) {
            console.log(c)
            var c = 3
        }
        c(2) // 报错
    </script>
</body>

</html>

以上是关于278 执行上下文执行上下文栈:变量提升与函数提升,执行上下文,执行上下文栈,全局执行上下文,函数执行上下文,练习题的主要内容,如果未能解决你的问题,请参考以下文章

# JavaScript中的执行上下文和队列(栈)的关系?

关于变量提升的理解

变量对象/变量提升

变量对象/变量提升

479 变量提升机制

原型模式故事链--JS执行上下文变量提升函数声明