目录
参考
基础用法
for循环
//在这里v输出的是下标
let arr = ['apple', 'orange']
for(let v=0; v<arr.length; v++) {
console.log(v, arr[v])
}
// 0, 'apple'
// 1, 'orange'
for…of(不能遍历对象)
- (可遍历map,object,array,set string等)用来遍历数据,比如组中的值
- 避免了for in的所有缺点,可以使用break,continue和return,不仅支持数组的遍历,还可以遍历类似数组的对象。
//在这里v输出的是内容
let arr = ['apple', 'orange']
for(let v of arr) {
console.log(v)
}
// 'apple'
// 'orange'
let objs = {
name: "vinc",
age: "18",
work: "it"
};
for (let v of Object.keys(objs)) {
console.log(v, objs[v]);
}
// 'name' 'vinc'
// 'age' '18'
// 'work' 'it'
for…in
用于循环遍历数组或对象属性
//在这里v输出的是下标
let arr = ['apple', 'orange']
for(let v in arr) {
console.log(v, arr[v])
}
// 0, 'apple'
// 1, 'orange'
map
- map不改变原数组但是会 返回新数组
- 可以使用break中断循环,可以使用return返回到外层函数
//在这里v输出的是下标
let arr = ['apple', 'orange']
let arrRes = arr.map(item => {
console.log(item);
return item
});
// 'apple'
// 'orange'
// 这里arrRes会返回一个新的数组, 数组中的元素为原始数组元素调用函数处理后的值
forEach
- 便利的时候更加简洁,效率和for循环相同,不用关心集合下标的问题,减少了出错的概率。
- 没有返回值
- 不能使用break中断循环,不能使用return返回到外层函数
let arr = ['apple', 'orange']
arr.forEach((item, index, arr) => {
console.log('元素:' item);
console.log('下标': index);
console.log('数组': arr);
});
终止循环
在以上的循环中如果需要终止后续的程序或者终止当前的循环可以使用到以下的方法: return break continue
let arr = ['apple', 'orange']
for(let v of arr) {
if(v == 'apple') {
continue;//跳出当前的循环,并不会终止;
}
return false;//终止循环 如果for循环中嵌套了for循环也将会终止
break;//用于跳出最近的一次循环,如果for循环中嵌套了for循环嵌套的循环将会继续执行
}
总结
- forEach 遍历列表值,不能使用 break 语句或使用 return 语句
- for in遍历对象键值(key),或者数组下标,不推荐循环一个数组
- for of 遍历列表值,允许遍历 Arrays(数组),Strings(字符串), Maps(映射), Sets(集合)等可迭代的数据结构等.在 ES6 中引入的 for of 循环,以替代
- for in 和 forEach() ,并支持新的迭代协议。
- for in循环出的是key,for of循环出的是value;
- for of是ES6新引入的特性。修复了ES5的for in的不足; for of不能循环普通的对象,需要通过和Object.keys()搭配使用
改变item
forEach
const list = [
{name: 'a', count: 1}, //object
2, // number
function fn() {
console.log(3);
},
Symbol(), // symbol
'sss', // string
[4,4,4,4], //Array
new Date() //date
]
list.forEach(item => {
item = 3
})
console.log(list)
改变item本身
内容都没有发生变化
改变item的属性的值
基础类型的,依旧没有发生改变。
引用类型的变量,如果自身带了count属性,该属性就会被修改;如果不带该属性,就会添加count属性。
for 和 for in
const list = [
{name: 'a', count: 1},
2,
function fn() {
console.log(3);
},
[4,4,4,4],
new Date()
]
for (let i = 0; i < list.length; i ++) {
list[i] = 4
}
//for(let i in list) {
// list[i] = 4
//}
console.log(list) // [ 4, 4, 4, 4, 4 ],全部被无差别覆盖了。
改变item本身
[ 4, 4, 4, 4, 4 ],全部被无差别覆盖了。
改变item的属性
[
{ name: 'a', count: 4 },
2,
[Function: fn] { count: 4 },
[ 4, 4, 4, 4, count: 4 ],
2022-09-13T10:44:50.164Z { count: 4 }
]
和forEach的时候,表现一致:
基础类型的,依旧没有发生改变。
引用类型的变量,如果自身带了count属性,该属性就会被修改;如果不带该属性,就会添加count属性。
for of
const list = [
{name: 'a', count: 1},
2,
function fn() {
console.log(3);
},
[4,4,4,4],
new Date()
]
for(let i of list) {
i = 4
}
console.log(list)
改变item本身
[
{ name: 'a', count: 1 },
2,
[Function: fn],
[ 4, 4, 4, 4 ],
2022-09-13T10:56:11.711Z
]
item无法被更改
改变item属性
[
{ name: 'a', count: 4 },
2,
[Function: fn] { count: 4 },
[ 4, 4, 4, 4, count: 4 ],
2022-09-13T10:57:36.085Z { count: 4 }
]
结果和forEach一致。他们都是在迭代函数里拿到了item。
map
const list = [
{name: 'a', count: 1},
2,
function fn() {
console.log(3);
},
Symbol(),
[4,4,4,4],
new Date()
]
list.map(item => {
item = 4
})
console.log(list)
改变item本身
[
{ name: 'a', count: 1 },
2,
[Function: fn],
Symbol(),
[ 4, 4, 4, 4 ],
2022-09-13T11:01:10.614Z
]
item没被改变
改变item属性
[
{ name: 'a', count: 4 },
2,
[Function: fn] { count: 4 },
Symbol(),
[ 4, 4, 4, 4, count: 4 ],
2022-09-13T10:59:53.050Z { count: 4 }
]
方式 | 取值方式 | 改变item自身 | 改变item的属性 |
---|---|---|---|
for | list[index] | 可以改变list[index] | 基础类型不可以改变,引用类型可以改变 |
for-in | list[index] | 可以改变list[index] | 基础类型不可以改变,引用类型可以改变 |
for-of | item | 不可以改变list[index] | 基础类型不可以改变,引用类型可以改变 |
forEach | item | 不可以改变list[index] | 基础类型不可以改变,引用类型可以改变 |
map | item | 不可以改变list[index] | 基础类型不可以改变,引用类型可以改变 |
forEach和map改变基本数据类型
// 基本类型可以欧~
const numArr = [33,4,55];
numArr.forEach((ele, index, arr) => {
if (ele === 33) {
arr[index] = 999
}
})
console.log(numArr); // [999, 4, 55]
// 引用类型也可以欧~
const allChangeArr = [{
name: 'wxw',
age: 22
}, {
name: 'wxw2',
age: 33
}]
allChangeArr.forEach((ele, index, arr) => {
if (ele.name === 'wxw2') {
arr[index] = {
name: 'change',
age: 77
}
}
})
console.log(allChangeArr); // // [{name: "wxw", age: 22},{name: "change", age: 77}]
forEach、map、for…of、for…in、for循环实现异步变同步
1、首先举个例子,执行test函数,要求先输出1、2、3、4、5,然后再输出“next”
let arr=[1,2,3,4,5];
function asyncEvent(ele){
setTimeout(e=>{
console.log(e);
},500,ele);
}
function test(){
arr.map( ele=> asyncEvent(ele));
console.log("next");
}
test();
2、从动画中可以看出,是先执行“next”,再执行数字,并且数字是同时展示出来的
解决方案
实现同步的方法
将要执行的异步方法封装成一个Promise返回,运用async/await方法,当异步函数里执行resolve时,await接收到成功的指示,然后进行下一步,实现结果如下
首先将异步函数用用Promise封装一下, 然后调用的时候用await去调用
let arr=[1,2,3,4,5];
function asyncEvent(ele){
return new Promise(resolve=>{
setTimeout(e=>{
console.log(e);
resolve(e)
},1000,ele);
})
}
for…of…
async function test(){
for(let i of arr){
await asyncEvent(i);
}
console.log("next");
}
test();
for ()循环
async function test(){
for(let i=0;i<arr.length;i++){
await asyncEvent(arr[i]);
}
console.log("next");
}
test();
for…in…
async function test(){
for(let i in arr){
await asyncEvent(arr[i]);
}
console.log("next");
}
test();
while(){}
async function test(){
let len=arr.length;
while(len--){
await asyncEvent(arr[len]);
}
console.log("next");
}
test();
Promise.all()
用这个方法,需要将接下来进行的操作放在then中执行,Promise.all会将几个异步操作并列执行,最终执行完成后的结果放在res中
async function test(){
Promise.all(arr.map( async ele=>{
return await asyncEvent(ele);
})).then(res=>{
console.log(res)
console.log("is start");
});
}
test();
不能实现同步的方法(以下方法实现不了,仅做错误实例)
forEach()
async function test(){
arr.forEach(async ele=> await asyncEvent(ele));
console.log("next");
}
test();
map()
async function test(){
arr.map(async ele=> await asyncEvent(ele));
console.log("next");
}
test();