最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 品一品JS 函数的执行时机

    正文概述 掘金(LuccaJ)   2021-05-01   549

    从一段代码讲起

    学习 JavaScript 的时候常常有一些困惑

    • 怎么会这样? ?
    • 什么原理呀? ?
    • JS 垃圾 !!! ?

    可是还得用 JavaScript 吃饭不是, 脑壳再疼也得好好理(tu)解(cao) JS 的原理!

    • 先来看一段十分普通的JavaScript代码,我们试图在控制台用循环语句输出几个数字。
    let i = 0
    for(i = 0; i<6; i++){
      console.log(i)
    }
    
    • 在Chrome中运行了一下,运行结果如下:
    品一品JS 函数的执行时机
    • 初学 JS 的老哥们都知道,结果是会输出从0到5的6个数。

    神奇的事情发生了

    • 下面我们给代码加点料,我们仍然使用同样的循环语句输出数字,只不过将console.log语句放在了setTimeout函数中且设置延时为0,看看控制台会输出什么结果?
    let i = 0
    for(i = 0; i<6; i++){
      setTimeout(()=>{
        // 延时函数
        console.log(i)
      },0)
    }
    
    • Chrome中运行结果是如下:

    品一品JS 函数的执行时机

    • 可以看到,Chrome浏览器的运行结果,居然在控制台打印出了6个6

    什么玩意儿?

    这是什么原理? 神奇的 JS 知识又要增加了么?

    首先来谈谈setTimeout函数

    setTimeout() 函数是干嘛的?

    • 查询mdn可以看到,文档中给出的描述是:
    • 再去W3School看看,他们给出的描述是:
    • 听起来似乎更容易理解了一些,看看代码示例也许更容易理解
    /* 浏览器3秒后向你打个招呼! */
    setTimeout(
      function(){
        alert("Hello"); 
      }, 3000);
    复制代码
    
    • 对于setTimeout()函数,更加白话的理解是:

    凡是放在这个函数中东西,都过一会再做,至于过多久,可以通过设定毫秒数来调节。

    那么如果将延时设置为0呢?

    • 用逻辑来理解的话,延时为0s === 不再过很久而是“**立即马上”**就做,可是“立即”究竟有多“立即”呢?“马上”究竟有多“马上”呢?
    • 要尝试理解“立即马上”,需要引入Event Loop的一些概念。

    当我们使用setTimeout() 时,到底发生了什么?

    • 接下来我们要看看当使用setTimeout() 时,到底发生了什么。

    setTimeout()究竟做了什么?

    ![image-20210501113639783](../../../Library/Application Support/typora-user-images/image-20210501113639783.png)

    一些术语的简单解释

    1. 调用栈(Call Stack)
    • MDN对于调用栈的解释大概是这样的:
    • 说白了就是:要执行的函数push到调用栈顶部,执行完从调用栈顶部pop出来,后进先出。
    1. 定时器(Timer)
    • 定时器可以理解为:定时执行某段代码,这里的setTimeout()函数就是JS为我们提供的一个定时器。
    1. Web APIs
    • Web APIs 是浏览器创建的一些线程,包含计时器等等。
    1. 回调序列(Callback queue)
    • 一个包含了回调函数的有序序列。

    **

    1. 事件循环(Event Loop)的简单描述
    • 事件循环包含了以下几个步骤:
      • 函数入栈执行,当执行到定时器(这类异步任务)时,把它丢给Web APIs去执行,接着继续执行栈内的剩余任务(同步任务),直到栈空;
      • 在此期间Web APIs会执行定时器,直到计时结束,然后会将回调函数(也就是setTimeout的第一个参数)扔到回调序列中;
      • 当调用栈为空时,事件循环会把Callback中的一个任务放入栈中,开始执行,回到第一步;

    图解setTimeout执行过程

    • 依旧是这段代码,我们用图解的形式理解一下。
    let i = 0
    for(i = 0; i<6; i++){
      setTimeout(()=>{
        console.log(i)
      },0)
    }
    
    1. 首先我们定义了变量i,并为它赋值,主程序开始。

    品一品JS 函数的执行时机

    1. 然后进入循环,循环的第一步就是判断i<6是否成立,需要把判断i<6的语句放入调用栈中执行。

    品一品JS 函数的执行时机

    1. 此时i的值是0,i<6显然成立,会继续执行循环体内的代码,即setTimeout(), 也就是压栈.

    品一品JS 函数的执行时机

    1. 作为一个定时器,setTimeout()会被扔到Web APIs中执行。

    品一品JS 函数的执行时机

    1. 此时,调用栈会继续执行后续代码,因为本次循环已经完成,所以会再次判断i<6,并进入下一次循环。

    品一品JS 函数的执行时机

    1. 几乎是在同一时刻(0s),计时器完成了计时,将回调函数扔到回调序列中。

    品一品JS 函数的执行时机

    1. 注意,这时候回调序列中的任务并不会马上执行,需要等到栈空才会开始进栈执行,因此会执行继续主程序。也就是循环体中的setTimeout(),因为是定时器,会被扔到Web APIs中执行。

    品一品JS 函数的执行时机

    1. 几乎是在同一时刻(0s),计时器完成了计时,将回调函数扔到回调序列中。

    品一品JS 函数的执行时机

    1. 如此循环往复,直到i的值变为6时,循环彻底结束,主程序也随之结束。

    品一品JS 函数的执行时机

    1. 此时回调序列中的任务还是进栈执行,打印i的值,而此时i的值为6,所以在控制台打印出了一个6。

    品一品JS 函数的执行时机

    1. 回调序列中的任务会逐一进栈执行,直至最后一个回调函数console.log() ,连续打印出六个6。

    品一品JS 函数的执行时机

    • 至此,我们基本解释了为何文章开头处那段代码会输出6个6,而不是0~5了。

    假如,我偏要输出“0~5”!!

    • 我们已经解释了为何那段代码会输出6个6,但是如果我偏要用for循环中嵌套setTimeout()的形式输出0~5呢?

    方案一

    • 在for循环体内声明i
    for(let i = 0; i<6; i++){
      setTimeout(() => {
      	console.log(i)
      }, 0)
    }
    

    方案二

    • 先声明函数,在setTimeout()中调用。
    let i = 0
    function cb() {
      console.log(i)
    }
    for(i = 0; i<6; i++){
      setTimeout(cb(), 0)
    }
    

    方案三

    • 使用立即执行函数?
    let i = 0
    for(i = 0; i<6; i++){
      (function(i){
      	setTimeout(() => {
      		console.log(i)
      	}, 0)
      })(i)
    }
    

    方案四

    for(var i = 1; i <= 5; i++) {
      setTimeout(console.log.bind(console, i), i * 1000);
    }
    

    Refenences


    起源地下载网 » 品一品JS 函数的执行时机

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元