JS 函数的执行时机

281 阅读2分钟

调用时机是JS函数的一个很重要的要数,调用时机不同,得到的结果就会不同。

首先示例一段代码:

let a =1 
functon fn(){
    console.log(a)
}
a = 2
fn()

打印出2,因为a=2后函数fn()才调用。

又有如下代码:

let a =1 
functon fn(){
    console.log(a)
}
fn()
a = 2

打印出1,因为先调用函数fn()后赋值a=2。

**setTimeout() 意思就是尽快,而不是马上;**其多用于在指定的毫秒数后调用函数或计算表达式。

let a = 1
function fn=(){
  setTimeout(()=>{
    console.log(a)
  },0)
}

fn()
a=2

打印出2,因为setTimeout()会让函数尽快打印出a的值,即整体先执行完在打印。

1、例如 有下代码:

let i = 0
for(i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

会打印 6 个 6

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

如何理解异步呢?

异步代码不等待结果,直接进行下面的代码,所以定时器只是开启了,而没有立即执行里面的代码,等到当前运行坏境的代码执行完之后再回来执行定时器里面的代码。总结:异步就是不等待结果的代码。

2 、写出让上面代码打印 0、1、2、3、4、5 的方法

for(let i = 0; i<6; i++){
  setTimeout(()=>{
    console.log(i)
  },0)
}

解释: 因为let变量的作用域只能在当前函数中,所以每次for循环生成的都是一个新的i, setTimeout里输出的i就是这个新的i,这个i是不会变化的,所以输出的就是正常的。

3、除了使用 for let 配合,还有什么其他方法可以打印出 0、1、2、3、4、5。

①闭包

let i 
for(i = 0; i<6; i++){
  !function(j){
      setTimeout(()=>{
        console.log(j)
      },0)
  }(i)
}

②利用 setTimeout 的第三个参数,将i传进去

let i
for(i = 0; i<6; i++){
    setTimeout((value)=>{
      console.log(value)
    },0,i)
}

③利用 const 关键字

let i
for(i = 0; i<6; i++){
    const x = i
    setTimeout(()=>{
      console.log(x)
    })
}

不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特・梵高