JS 函数的执行时机1

79 阅读2分钟
调用时机

JS函数的不同执行时机,会影响到函数运行的输出结果,不能通过代码本身百分百判断函数输出什么,而是要根据函数具体的执行时机,一个函数的调用时机会影响其结果

从函数调用的角度看,分为同步函数和异步函数

  • 同步函数:当一个函数是同步执行时,那么当函数被调用的时候不会立即返回,直到函数要做的事情全部做完才返回
  • 异步函数:如果一个异步函数被调用的时候,该函数会立即返回,尽管该函数规定的操作任务还没有完成
定时器:setTimeout()
  • 用于在指定的毫秒数后调用函数或计算表达式;
  • 语法:setTimeout(x,y,z)。x 函数function();y 时间(time);z 参数(会自动传入第一个参数,也就是函数的参数中) 可省略
  • 要先把主代码运行完再运行setTimeout里面的代码
    (通俗比喻:老板让清点箱子,清一半的时候老板说尽快写纸上交给我,当下没清点完成肯定不能写,要等全部数清以后才能写下来交给老板)
思考1:下面代码打印出什么
let i=0
for(i=0;i<6;i++){
    setTimeout(()=>{
        console.log(i)
    },0)
}

输出:
1.png
解释: setTimeout是一个异步任务,执行到这里的操作会被浏览器丢到另一个任务队列里去, 浏览器这时候会继续执行for循环。每一次for循环的时候,setTimeout都执行一次,但是里面的函数没有被执行,而是被放到了任务队列里面,等待执行,for循环了6次,就放了6次,当主线程执行完成后,才进入任务队列里面执行。这时候因为for循环i=6了,所以输出的全部都是6。

由于setTimeout的原因,将原本要即时打印的结果延迟到for循环结束之后,所以这里结果是for循环结束才开始打印执行的,且只有1个i,i的值已经是5,再执行i++, 所以连续打印6个6出来

如何打印 0、1、2、3、4、5
  • 方法一:把i定义在循环内,每次for循环的时候i都有一个单独的作用域
for(let i=0;i<6;i++){
    setTimeout(()=>{ console.log(i) },10)
}
  • 方法二
for(i=0;i<6;i++){
 let a = i
 setTimeout(()=>{ console.log(a) },10)
}
  • 方法三(增加一个立即执行函数),for循环里没有变量i,所以匿名函数和外边的i形成一个闭包
let i=0
for(i=0;i<6;i++){
    !function (i) {
       setTimeout(()=>{console.log(i)},0)  
    }(i)
}