2

前段的功能越来越强大,现在实现同步的for循环输出的方式也越来越多,我们先看一个例子:

forF();
function forF() {
  for (var i = 0; i < 3; i++) {
    setTimeout(function () {
      console.log(i);
    }, 1000)
  }
}
// 1s后输出:3 3 3

相信大家对这个比较常见了,原理是因为var声明的i为forF的局部变量,setTimeout只是定时器,他暂时将内部函数挂起,等到一秒后执行,到那个时候,i已经变成了5。

那么我们的解决办法有哪些呢?

先上一个es5以前的解决办法:

forF();
function forF() {
  for (var i = 0; i < 3; i++) {
    outF(i);
  }
}

function outF(i) {
  setTimeout(function () {
    console.log(i);
  }, 1000*i)
}
// 0 1 2

因为在循环中用了外部函数,那么相当于创建了三个outF实例,因为i是基本变量,所以每个实例的i都是不共享的,这里要注意设置的定时器时间要1000*i;

下面开始用es6的方法实现啦!
1.用块作用域的let

forF();
function forF() {
  for (let i = 0; i < 3; i++) {
    setTimeout(function () {
      console.log(i);
    }, 1000*i)
  }
}

因为let是块作用域的,对于setTimeout函数而言,每次循环都新创建一个i,每个i不共享

2.await(其实是es7的)
见代码

var sleep = function (time) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve('ok');
        }, time);
    })
};
// // 用await实现循环输出数字
async function awaitF() {
  for (var i = 0; i < 3; i++) {
    await sleep(1000);
    console.log(i)
  }
}
awaitF()
// 0 1 2

await顾名思义是等待,他接受一个promise对象,等待他相应然后才继续执行。
注意用await的函数必须加async关键字
关于promise,推荐看大白话:https://www.cnblogs.com/lvdab...

3.yeild

function* countAppleSales () {
  for (var i = 0; i < 3; i++) {
    yield;
    console.log(i);
  }
}

var appleStore = countAppleSales(); // Generator { }
appleStore.next();
nextApp(appleStore);
function nextApp(appleStore) {
  setTimeout(function () {
    let done = appleStore.next().done;
    if (!done) {
      nextApp(appleStore);
    }
  }, 1000);
}

yield函数必须定义成function* 外部在调用此函数的时候必须用next()方法他才会继续执行到下个yeild那里,所以这里用递归去执行。
关于yeild的知识点百度也很多,可自行百度。


后续会更新,欢迎补充


前端spark
567 声望9 粉丝

爱生活,爱编程