JS函数版‘’刻舟求剑“

289 阅读2分钟

导论: 函数的九个孩子

  • 调用时机

  • 作用域
  • 闭包
  • 形参
  • 返回值
  • 调用栈
  • 函数提升
  • arguements(除了箭头函数)
  • this(除了箭头函数)

我们今天来讲讲JS版的 刻舟求剑

接下来看一个栗子:

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。

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

就好比生活中的栗子:

下午5点30分,由于疫情影响,大人生活变得越来越规律了,而你这个时候正在吃鸡,眼中着,P城就剩俩人了,这个时候来自麻麻的灵魂召唤:“伢嘞,吃饭喽!”,这个时候你是不是很纠结!但是不能让自己的辛苦白费,必须吃鸡,才去吃饭!!!若干分钟以后,你做出回应:“娘嘞,俺来了!!”

那如何解决这种情况呢?

请看一下的代码(神来之笔


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

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

碎碎念:有没有另外一种解决方式呢?

  • 可以用 setTimeout 的第三个参数,将i传进去
let i
for(i = 0; i<6; i++){
    setTimeout((hejiajin)=>{
      console.log(hejiajin)
    },0,i)
}

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

总结:JS函数的调用时机不同,得到的结果不同。setTimeout()其意思就是尽快,而不是马上。(MDN)