IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 执行上下文与执行上下文栈 -> 正文阅读

[游戏开发]执行上下文与执行上下文栈

变量提升与函数提升

变量声明提升

通过var定义(声明)的变量,在定义语句之前就可以访问到,但是值是: undefined
eg:

        console.log(b)
        var b =3;

输出:

undefined

注意:必须是通过var定义的变量,如果一个变量没有通过var定义特就不会进行提升。

函数声明提升

通过function声明的函数,在定义之前就可以直接调用,并且值就是函数所定义的内容(对象)。
eg:

        fun()
        function fun (){
           console.log('我是fun')
        }

输出:

我是fun

函数提升必须使用声明的方式定义函数,如果使用变量的方式定义函数就是变量提升了。
eg:

       fun()
        var fun = function (){
           console.log('我是fun')
        }

输出:
在这里插入图片描述

函数提升和变量提升的先后书顺序

先执行变量提升,再执行函数提升
eg:

      function a() {}
      var a;
      console.log(typeof a);

输出:

function

那么为什么会有声明提升呢?下面就会介绍

代码分类

代码分为全局代码与局部(函数)代码

执行上下文

全局执行上下文

  • 在执行全局代码前将window确定为全局执行上下文
  • 对全局数据进行预处理:
    var定义的全局变量==>undefined,添加为window的属性,即放到全局执行上下文中
    function声明的全局函数==>赋值(fun),赋值为函数对象(创建了函数对象但是没有执行函数),添加为window的方法,即放到全局执行上下文中
    this==>赋值(window)
  • 开始执行全局代码
    执行全局代码的时候会跳过预处理时已经处理过的代码片段(主要是函数)
    注意: 预处理不是执行函数,而是执行函数定义,即只创建了函数对象,真正执行函数还要看执行代码时什么时候调用函数。
    如果执行过程中遇到 var定义的全局变量、function声明的全局函数、this,就会去全局执行上下文window中寻找。
    eg:
        // 全局执行上下文
        console.log(a1, window.a1)
        a2()
        console.log(this)

        var a1 = 3
        function a2 (){
           console.log('a2()')
        }
        console.log(a1)

输出:
在这里插入图片描述
断点调试
在这里插入图片描述
16 ==>17 ==>18 ==>19 ==>20 ==>24,
到20行后就直接到24行,因为在预处理的时候就已经创建过函数对象了。
补充:执行到17行后直接执行18行,这里虽然不显示执行过程,但是函数 a2 仍然是在17行调用的时候执行的,预处理只是为其定义对象。)

eg2:有参数的函数
在这里插入图片描述
14行==> 27行==>28行
不显示执行过程,但是函数 fn 是在27行调用的时候执行的

函数执行上下文

  • 调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(全局的时候直接使用window即可,无需再创建对象)
  • 对局部数据进行预处理
    形参变量==>赋值(实参)==>添加为执行上下文的属性
    arguments==>赋值(实参列表),添加为执行上下文的属性
    var定义的局部变量==>undefined,添加为执行上下文的属性
    function声明的函数==>赋值(fun),赋值为函数对象(创建了函数对象但是没有执行函数),添加为执行上下文的方法
    this==>赋值(调用函数的对象: window 或其他对象)
  • 开始执行函数体代码
    执行函数体的时候会跳过预处理时已经处理过的代码片段。
    如果执行过程中遇到 形参变量、 arguments、var定义的全局变量、function声明的全局函数、 this,就会去函数执行上下文对象中寻找。

函数执行上下文对象实际上是一个虚拟对象,是一个区域,该区域中存放预处理的变乱给、函数等,存放在栈中(局部变量存放在栈中)。
不调用就不会出现函数执行上下文。

局部变量的区域是封闭的,而且函数执行完毕之后局部变量就会消失。

eg:

    function fn (a1){
        console.log(a1)//2
        console.log(a2)//undefined
        a3()//a3()
        console.log(this)//window
        console.log(arguments)//伪数组(2,3)
      
       var a2 =3
       function a3 (){
          console.log("a3()")
       }
    }
    fn(2,3)

输出:
在这里插入图片描述
正式由于全局执行上下文和函数执行上下文的存在才会使函数与变量的声明提前。

执行上下文栈

引例

判断下面的代码是否会出错:

    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函数在foo声明之前就调用foo,而且foo函数不是用声明的方式定义函数,即不会出现函数提前声明,乍一看是会出错的,但是再仔细看一下。
var bar =function(x), var foo = function (y) 他们是一个赋值语句只不过赋的值是函数,但是赋值不代表函数执行,函数在调用的时候才会执行。也就是说先依次声明了bar、foo变量(函数),到后面执行bar函数的时候,foo函数已经声明好了,自然不会报错。

执行上下文数目

执行上下文包括全局执行上下文和函数执行上下文,每次执行代码就会产生一个全局上下文window,每调用一次函数就会产生一个函数执行上下文。
所以产生的执行上下文数目 = 调用函数的次数 + 1
eg: 上述引例就产生了 3 个执行上下文

执行上下文的管理——执行上下文栈

一个函数代码可能会产生很多个执行上下文,所以我们需要对他们进行管理。
我们采用栈结构进行管理:
执行过程:
1.在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象
2.在全局执行上下文(window)确定后,将其添加到栈中(压栈)
3.在函数执行上下文创建后,将其添加到栈中(压栈)
4.在当前函数执行完后,将栈顶的对象移除(出栈)
5.当所有的代码执行完后,栈中只剩下window

eg:

    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)

对应的执行上下文栈就是:
在这里插入图片描述

特点

  • 采用栈结构,先进后出
  • 栈底永远是全局执行上下文环境window,其余的都是函数执行上下文
  • 当前正在运行的永远是栈顶的执行上下文

题目

题1

    console.log('global begin:'+ i)
    var i =1

    foo(1)
    function foo (i){
        if(i==4){
        return;
        }
        console.log('foo() begin:'+i)
        // 递归调用:在函数内部调用自己
        foo(i+1)
        console.log('foo() end:'+i)
    }

    console.log('global() end:'+i)

输出什么?
在这里插入图片描述
对应的执行上下文栈?
产生了5个执行上下文栈:
在这里插入图片描述

题2

  • 1
   function a() {}
      var a;
      console.log(typeof a);

输出:

function

因为先执行变量提升,再执行函数提升

  • 2
    if(!(b in window)){
        var b =1;
    }
    console.log(b)//undefined

输出:

undefined

因为b in window为真

  • 3
  var c =1
    function c (c){
       console.log(c)
    }
    c(2)//报错  

输出:

Uncaught TypeError: c is not a function

原因:因为预处理先执行变量提升,再执行函数提升,但是不会为变量赋值,所以上面的代码就相当于

    var c
    function c (c){
       console.log(c)
    }
    c=1
    c(2)

所以自然报错。

问题:与预处理的时候函数是否执行

有两个概念:

  • 执行函数定义:就是函数的定义,并没有真正的执行函数,只是创建了行数对象。

  • 执行函数:执行函数体,真正的执行函数
    预处理函数就是执行函数定义,所以并未执行函数

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2022-04-27 11:37:15  更:2022-04-27 11:37:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/17 1:15:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码