经典闭包处理

1:闭包

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

console.log(new Date(), i) // 5 -> 5,5,5,5,5
1
2
3
4
5
6
7

改进一:IIFE

for (var i = 0; i < 5; i++) {
  ;(function (j) {
    // j = i
    setTimeout(function () {
      console.log(new Date(), j)
    }, 1000)
  })(i)
}

console.log(new Date(), i)
1
2
3
4
5
6
7
8
9
10

改进二:setTimeout 传值

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

console.log(new Date(), i)
1
2
3
4
5
6
7
8
9
10
11

改进三:函数传值

var output = function (i) {
  setTimeout(function () {
    console.log(new Date(), i)
  }, 1000)
}

for (var i = 0; i < 5; i++) {
  output(i) // 这里传过去的 i 值被复制了
}

console.log(new Date(), i)
1
2
3
4
5
6
7
8
9
10
11

改进四:使用 let

for (let i = 0; i < 5; i++) {
  setTimeout(
    function (j) {
      console.log(new Date(), j)
    },
    1000,
    i
  )
}

console.log(new Date(), i)
1
2
3
4
5
6
7
8
9
10
11

1:ES6

  • 0 -> 1 -> 2 -> 3 -> 4 -> 5

方案一:setTimeout 异步

for (var i = 0; i < 5; i++) {
  ;(function (j) {
    setTimeout(function () {
      console.log(new Date(), j)
    }, 1000 * j) // 这里修改 0~4 的定时器时间
  })(i)
}

setTimeout(function () {
  // 这里增加定时器,超时设置为 5 秒
  console.log(new Date(), i)
}, 1000 * i)
1
2
3
4
5
6
7
8
9
10
11
12

方案二:promise 异步

const tasks = [] // 这里存放异步操作的 Promise
const output = (i) =>
  new Promise((resolve) => {
    setTimeout(() => {
      console.log(new Date(), i)
      resolve()
    }, 1000 * i)
  })

// 生成全部的异步操作
for (var i = 0; i < 5; i++) {
  tasks.push(output(i))
}

// 异步操作完成之后,输出最后的 i
Promise.all(tasks).then(() => {
  setTimeout(() => {
    console.log(new Date(), i)
  }, 1000)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

3:ES7

改进一:async/await

// 模拟其他语言中的 sleep,实际上可以是任何异步操作
const sleep = (timeountMS) =>
  new Promise((resolve) => {
    setTimeout(resolve, timeountMS)
  })

;(async () => {
  // 声明即执行的 async 函数表达式
  for (var i = 0; i < 5; i++) {
    if (i > 0) {
      await sleep(1000)
    }
    console.log(new Date(), i)
  }

  await sleep(1000)
  console.log(new Date(), i)
})()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

改进二:Generator?

上次更新:
(adsbygoogle = window.adsbygoogle || []).push({});