Open maicFir opened 2 years ago
你知道 JS 中断循环有哪些吗?除了 for 循环的 break,还有哪些可以中断循环?接下来笔者以实际业务例子,分享几种能中断循环的方案,希望你在实际业务中能用得上。
在实际业务中你可能会写以下的业务代码,举个栗子,在一个循环表单域中,你需要内容为空,就禁止提交
在一个循环表单域中,你需要内容为空,就禁止提交
::: details code
const shopList = [ { title: 'Apple', price: 10 }, { title: 'banana', price: '' }, { title: 'orange', price: 5 } ];
:::
以上是一组数组源,于是你的思路可能会这样
const hasPriceEmpty = (arr) => { bool = false; // 默认都不是空 arr.forEach((v) => { if (v.price === '') { bool = true; break; } console.log(v); }); return bool; }; const handleSubmit = () => { if (hasPriceEmpty(shopList)) { return; } // 下面的继续业务操作 console.log('go on...'); }; handleSubmit();
运行测试命令node 1.js,报错了!
node 1.js,
于是你把 break 改成 return
const hasPriceEmpty = (arr) => { bool = false; // 默认都不是空 arr.forEach((v) => { if (v.price === '') { bool = true; return; } console.log(v); }); return bool; }; ...
你会发现并没有打印go on...,确实是hasPriceEmpty这个方法已经达到了自己的业务要求,但是打印出了第一组和第三组数据。
go on...
hasPriceEmpty
于是mdn上关于 forEach 有这么一段话,Note: There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
mdn
Note: There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
大概意思就是除了抛出异常,break 无法中断循环,如果你想有中断行为,forEach不是一个好办法。
forEach
于是你想中断循环,你改了下代码 ::: details code
const shopList = [ { title: 'Apple', price: 10 }, { title: 'banana', price: '' }, { title: 'orange', price: 5 } ]; const hasPriceEmpty = (arr) => { bool = false; // 默认都不是空 arr.forEach((v) => { if (v.price === '') { bool = true; throw new Error('给我中断循环吧'); } try { console.log(v); } catch (e) { console.log(e); console.log(v); } }); return bool; }; const handleSubmit = () => { if (hasPriceEmpty(shopList)) { return; } // 下面的继续业务操作 console.log('go on...'); }; handleSubmit();
对不起,页面只打印了第一组数据,且页面抛出了异常 我确实做到了中断 forEach 循环异常了,但是这个错误作为一个强迫症患者,我是不能接受的(throw 抛出的异常,记得 try catch 中捕获)。
这是笔者认为大部分人都能想到的办法 ::: details code
const shopList = [ { title: 'Apple', price: 10 }, { title: 'banana', price: '' }, { title: 'orange', price: 5 } ]; const hasPriceEmpty = (arr) => { let bool = false; // 默认都不是空 for (let i = 0, len = arr.length; i < len; i++) { if (arr[i].price === '') { bool = true; break; } console.log(arr[i]); } return bool; }; const handleSubmit = () => { if (hasPriceEmpty(shopList)) { return; } // 下面的继续业务操作 console.log('go on...'); }; handleSubmit();
结果很令人欢喜,完美
通常这种方式用得最多,但是作为老司机,你还需要掌握多一点其他方法。于是中断循环还有...
const shopList = [ { title: 'Apple', price: 10 }, { title: 'banana', price: '' }, { title: 'orange', price: 5 } ]; const hasPriceEmpty = (arr) => { let bool = false; // 默认都不是空 let index = 0; while (index < arr.length) { index++; console.log(arr[index], '000'); if (arr[index].price === '') { bool = true; break; } console.log(arr[index], '111'); } return bool; }; const handleSubmit = () => { if (hasPriceEmpty(shopList)) { return; } // 下面的继续业务操作 console.log('go on...'); }; handleSubmit();
结果喜大普奔,依然可以,测试结果如下
这已经达到我们想要的效果了。
利用 iterable 迭代器,for...of 中断循环
这里iterable是指具有该特性的迭代器,比如Array、Map、Set
iterable
Array
Map
Set
const shopList = [ { title: 'Apple', price: 10 }, { title: 'banana', price: '' }, { title: 'orange', price: 5 } ]; const hasPriceEmpty = (arr) => { let bool = false; // 默认都不是空 for (let item of arr) { if (item.price === '') { bool = true; break; } console.log(item, '111'); } return bool; }; const handleSubmit = () => { if (hasPriceEmpty(shopList)) { return; } // 下面的继续业务操作 console.log('go on...'); }; handleSubmit();
于是测试结果依旧 ok
为什么数组可以用for..of循环,你可以在控制台打印注意到
for..of
原来默认申明的[]原型链上有一个这样的iterator的迭代器,所以你可以利用 iterator 的特性,用for...of中断循环
[]
iterator
for...of
const shopList = [ { title: 'Apple', price: 10 }, { title: 'banana', price: '' }, { title: 'orange', price: 5 } ]; const hasPriceEmpty = (arr) => { let bool = false; // 默认都不是空 const map = new Map(); // 将数据设置到Map中 arr.forEach((item) => { map.set(item.title, item); }); for (let s of map) { console.log(s, '000'); if (s[1].price === '') { bool = true; break; } console.log(s, '111'); } return bool; }; const handleSubmit = () => { if (hasPriceEmpty(shopList)) { return; } // 下面的继续业务操作 console.log('go on...'); }; handleSubmit();
结果如下
以上代码也等价于 ::: details code
const sourceData = [ { title: 'Apple', price: 10 }, { title: 'banana', price: '' }, { title: 'orange', price: 5 } ]; const shopList = new Map([sourceData]); const hasPriceEmpty = (arr) => { let bool = false; // 默认都不是空 for (let s of arr) { console.log(s, '000'); if (s[1].price === '') { bool = true; break; } console.log(s, '111'); } return bool; }; const handleSubmit = () => { if (hasPriceEmpty(shopList)) { return; } // 下面的继续业务操作 console.log('go on...'); }; handleSubmit();
::: 验证结果如下:
利用 Map 有iterable的可迭代性,通过for...of中断循环,具体可以在控制台下验证
同样是一个栗子举证 ::: details code
const shopList = [ { title: 'Apple', price: 10 }, { title: 'banana', price: '' }, { title: 'orange', price: 5 } ]; const hasPriceEmpty = (arr) => { let bool = false; // 默认都不是空 const setArr = new Set([...shopList]); for (let s of setArr) { console.log(s, '000'); if (s.price === '') { bool = true; break; } console.log(s, '111'); } return bool; }; const handleSubmit = () => { if (hasPriceEmpty(shopList)) { return; } // 下面的继续业务操作 console.log('go on...'); }; handleSubmit();
输出验证结果:
Set与Map一样,可以在控制台验证一下iterable属性,我就不验证了,呜呜。
1.forEach的中断循环可以抛异常来达到目的,但是不适合此业务场景
2.for 循环通用大法,break可以终止循环
for
break
3.while循环,break也可以终止循环
while
4.iterable特征的可迭代器,for...of,break中断循环,并且最重要的一点是在 break 后,当前索引条件不会继续执行,也就是 for...of 中,执行 break 后,后面语句都不会执行。
5.本文示例code-example
你知道 JS 中断循环有哪些吗?除了 for 循环的 break,还有哪些可以中断循环?接下来笔者以实际业务例子,分享几种能中断循环的方案,希望你在实际业务中能用得上。
forEach
在实际业务中你可能会写以下的业务代码,举个栗子,
在一个循环表单域中,你需要内容为空,就禁止提交
::: details code
:::
以上是一组数组源,于是你的思路可能会这样
::: details code
:::
运行测试命令
node 1.js,
报错了!于是你把 break 改成 return
::: details code
:::
你会发现并没有打印
go on...
,确实是hasPriceEmpty
这个方法已经达到了自己的业务要求,但是打印出了第一组和第三组数据。于是
mdn
上关于 forEach 有这么一段话,Note: There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
大概意思就是除了抛出异常,break 无法中断循环,如果你想有中断行为,
forEach
不是一个好办法。于是你想中断循环,你改了下代码 ::: details code
:::
对不起,页面只打印了第一组数据,且页面抛出了异常 我确实做到了中断 forEach 循环异常了,但是这个错误作为一个强迫症患者,我是不能接受的(throw 抛出的异常,记得 try catch 中捕获)。
for 循环 break 中断
这是笔者认为大部分人都能想到的办法 ::: details code
:::
结果很令人欢喜,完美
通常这种方式用得最多,但是作为老司机,你还需要掌握多一点其他方法。于是中断循环还有...
while 循环中断
::: details code
:::
结果喜大普奔,依然可以,测试结果如下
这已经达到我们想要的效果了。
利用 iterable 迭代器,for...of 中断循环
这里
iterable
是指具有该特性的迭代器,比如Array
、Map
、Set
Array
::: details code
:::
于是测试结果依旧 ok
为什么数组可以用
for..of
循环,你可以在控制台打印注意到原来默认申明的
[]
原型链上有一个这样的iterator
的迭代器,所以你可以利用 iterator 的特性,用for...of
中断循环Map
::: details code
:::
结果如下
以上代码也等价于 ::: details code
::: 验证结果如下:
利用 Map 有
iterable
的可迭代性,通过for...of
中断循环,具体可以在控制台下验证Set
同样是一个栗子举证 ::: details code
:::
输出验证结果:
Set
与Map
一样,可以在控制台验证一下iterable
属性,我就不验证了,呜呜。总结
1.
forEach
的中断循环可以抛异常来达到目的,但是不适合此业务场景2.
for
循环通用大法,break
可以终止循环3.
while
循环,break
也可以终止循环4.
iterable
特征的可迭代器,for...of
,break
中断循环,并且最重要的一点是在 break 后,当前索引条件不会继续执行,也就是 for...of 中,执行 break 后,后面语句都不会执行。5.本文示例code-example