zoukankan      html  css  js  c++  java
  • javaScript中的同步,异步与回调函数





    for
    (var i = 0; i < 5; i++) { setTimeout(function() { console.log('i: ',i); }, 1000); } console.log(i);

    输出结果:

    //输出
    5
    i:  5
    i:  5
    i:  5
    i:  5
    i:  5

    记住我们的口诀,同步=>异步=>回调

    1、for循环和循环体外部的console是同步的,所以先执行for循环,再执行外部的console.log。(同步优先)
     
    2、for循环里面有一个setTimeout回调,他是垫底的存在,只能最后执行。(回调垫底)
    那么,为什么我们最先输出的是5呢?
     
    非常好理解,for循环先执行,但是不会给setTimeout传参(回调垫底),
    等for循环执行完,就会给setTimeout传参,而外部的console打印出5是因为for循环执行完成了。
     
    这里涉及到JavaScript执行栈和消息队列的概念,概念的详细解释可以看阮老师的 JavaScript 运行机制详解:再谈Event Loop – 阮一峰的网络日志,或者看 并发模型与Event Loop。
     
       javaScript单线程如何处理回调呢?
    javaScript同步的代码是在堆栈中顺序执行的。而setTimeout回调会先放到消息队列,for循环每执行一次,就会
    放一个setTimeout到消息队列中,排队等候,当同步代码执行完了,再去调用消息队列中的回调方法。
     
    在这个经典例子中,也就是说,先执行for循环,按顺序放了5个setTimeout回调到消息队列,然后for循环结束,下面还有一个同步的console,执行完console之后,堆栈中已经没有同步的代码了,就去消息队列找,发现找到了5个setTimeout,注意setTimeout是有顺序的。
     
    那么,setTimeout既然在最后才执行,那么他输出的i又是什么呢?答案就是5。。有人说不是废话吗?
     
    现在告诉大家为什么setTimeout全都是5,JavaScript在把setTimeout放到消息队列的过程中,循环的i是不会及时保存进去的,相当于你写了一个异步的方法,但是ajax的结果还没返回,只能等到返回之后才能传参到异步函数中。
    在这里也是一样,for循环结束之后,因为i是用var定义的,所以var是全局变量(这里没有函数,如果有就是函数内部的变量),这个时候的i是5,从外部的console输出结果就可以知道。那么当执行setTimeout的时候,由于全局变量的i已经是5了,所以传入setTimeout中的每个参数都是5。
     
  • 相关阅读:
    1203—颜文生—自动机实验
    11-11 优点缺点评价
    操作系统之银行家算法避免死锁
    操作系统之实验三 进程调度模拟程序
    操作系统之实验二作业调度模拟程序
    操作系统之实验二Step1-有序顺序表
    复利计算程序的单元测试
    操作系统之实验一 命令解释程序的编写
    复利计算程序之最新版
    《构建之法》第1.2.3章的感悟
  • 原文地址:https://www.cnblogs.com/qianxunpu/p/7767706.html
Copyright © 2011-2022 走看看