JavaScript 之 常用的循环数组的方法、循环的控制以及各自的区别、注意点(如:forEach()、map()、filter())

  所谓循环,就是重复 ,重复的执行一段代码,前提是重复要有尽头,不能无穷无尽的无休止重复下去。
  循环有4个要素:
    1)有一个初始值表达式
    2)条件判断表达式
    3)要重复执行的代码表达式
    4)改变初始化变量(重要,千万不要写死循环)
  JavaScript 中的循环语句有哪些?各自的特点又有什么不同呢?……下面,就让我们逐一解开。

常用循环语句

1、for 循环

  语法:

for ( 初始值; 条件判断; 改变初始值 ) { 满足条件时重复执行的代码 }

  语法示例:

for(var i = 0; i < 10; i++){ console.log(i) };

  剖析:
    for 循环的代码执行顺序

	var i = 0;           // 第一步:初始值
    i < 10;              // 第二步:条件判断
    console.log(i);      // 第三步:条件满足时执行的代码
    i++;                 // 第四步:改变初始值
    ...                  // 一直重复执行 2 3 4 步,直到条件不满足时停止执行。

注意:for()里面的初始值; 条件判断; 改变初始值这三个表达式是用分号隔开,不是逗号!分号隔开,不是逗号!分号隔开,不是逗号!

2、循环的控制

  控制循环的关键字
    1)break:当循环里面,只要代码执行了 break,那么就立即结束循环, 跳到循环外面;
      示例:

for (var i = 1; i <= 10; i++) {
    console.log('我吃的第' + i + '个包子')
    if (i === 4) {
        // 表示我已经吃了4个包子了, 吃不下了
        // 后面的5 6 7 8 9 10 我就不吃了
        break
    }
}

在这里插入图片描述

    2)continue:当循环里面,只要代码执行了 continue,就立即结束本次循环, 直接进入下一次循环。
      示例:

for (var i = 1; i <= 10; i++) {
    if(i === 5){
        // 这个包子我不吃了, 我直接跳过去吃下一个包子
        // continue 后面的代码就不执行了, 直接去到 i++
        continue
    }
    console.log('我吃的第 ' + i + ' 个包子')
}

在这里插入图片描述

3、for in 循环

  for in 循环是基于 for 循环的基础上的一种特殊的循环。

  语法示例:

var arr = [12, 23, 34, 45, 56];
for(var i in arr){
    if(i == 0) {
        console.log('停止当前循环,continue');
    }
    if(i == 2) {
        console.log('当i = 2时')
        break;
        // return; // 不能使用return,报错:Illegal return statement(非法的返回语句)
    }
    console.log('i', i, 'i的类型', typeof i);
    console.log(arr[i]);   // 打印结果为 12 23 34 45 56 
}

在这里插入图片描述
如图所示:

for in 循环支持break 结束循环,但是不支持 continue

  剖析:
    从语法示例上我们可以看出,for in 循环代码更加简洁,但同时伴随着一定的弊端:
    for in 循环和普通 for 循环的区别:
      1、在循环数组时,for in 循环给循环变量赋值为字符串类型,而普通 for循环给循环变量赋值为数值类型
      2、在循环对象时,for in循环可以循环对象,而普通for循环,不能直接循环对象。其实,for in 循环在循环数组时就是把数组当成了对象来循环,数组的下标就是相当于对象中键值对的键,而浏览器在处理数组时,也可以把数组当成对象,就像盛行的一句行话:万物皆对象。

  剖析 for in 循环代码如下:

var arr = [12, 23, 34, 45, 56];
// 数组arr当成对象之后的解析如下
arr={
    "0": 12,
    "1": 23,
    "2": 34,
    "3": 45,
    "4": 56,
}
var arr = [12, 23, 34, 45, 56];
for(var i in arr){
    console.log(arr[i]);  // 打印结果为 12 23 34 45 56      
    console.log(typeof arr[i]);    // 打印结果为 number 
    console.log(i);     // 打印循环变量结果为 0 1 2 3 4
    console.log(typeof i);      // 打印循环变量类型为 string 类型
 }

4、for of 循环

  注:for of 循环只能循环具有长度含义( length 或者size )属性的数据类型
  语法示例:

  • 循环字符串
let str = 'abcd';
console.log(str.length);  // 4
for(let i of str) {
    if(i == 'b') {
        continue;
    }
    if(i == 'd') {
        break;
    }
    console.log('i', i);  // a   b   c  d
}

在这里插入图片描述

  • 循环数组
let arr = [12, 23, 34, 45, 56];
console.log(arr.length);  // 5
for(let i of arr){
    if(i == 23) {
        continue;
    }
    if(i == 45) {
        break;
    }
    console.log('i', i, '= i 的类型 = ', typeof i);
}

在这里插入图片描述

  • 循环伪数组
let s1 = new Set([12, 23, 34, 45, 56]);
console.log(s1.size);
for(let item of s1){
    if(item == 23) {
        continue;
    }
    if(item == 45) {
        break;
    }
    console.log('item', item, '= item 的类型 = ', typeof item);
}

在这里插入图片描述

  注:循环变量为该数据中的每一个下标对应的数据;

  • 循环对象
      当循环的数据类型没有长度含义( length 或者 size )属性时:
let obj = {
    name: 'aaa',
    age: 12
}
console.log(obj.length); // undefined

for(let i of obj){
    console.log(i);  // TypeError: obj is not iterable  报错!!!
}

5、while 循环

  语法:

while (判断条件) { 条件满足时重复执行的代码 }

  语法示例:

var i = 1;				// 第一步:初始值
while(i <= 10){			// 第二步:条件判断
    // if(i == 2) {
    //     continue;  // 不能在第四步改变初始值的之前写 continue,不然会陷入死循环
    // }
    if(i == 6) {
        break;
    }
    console.log('i', i, '= i 的类型 = ', typeof i);		// 第三步:条件满足时执行的代码
    i++;				// 第四步:改变初始值
    if(i == 2) {
        continue;  // 在这里写的continue 没有意义,因为代码执行到这里的时候本就会继续执行下去
    }
}

写了continue 的控制台打印:
在这里插入图片描述
没写 continue 的控制台打印:
在这里插入图片描述
这两者的结果是一样的。

  剖析:
    while 的中文释义为当…的时候,那么我们就需要在执行 while 语句时先有一个初始值,并给初始值设定一个范围一个条件,条件满足时执行重复的代码,最后再改变初始值。
    剖析后,很明显,while 循环和 for 循环剖析后的大同小异,执行顺序都是如此重复执行第 2 3 4 步的代码,直到条件不满足时结束循环。

6、do…while 循环

  语法:

do {
    重复执行的代码
} while (条件)

do...while 循环与 while 循环的代码执行顺序基本一致,break、continue的用法也与普通 while 一致,在此便不多做演示;

    var i = 1			// 1. 初始化变量
    do {
      console.log(i)	// 3. 重复执行的代码
      i++				// 4. 改变自身
    } while (i < 10)	// 2. 条件判断

  只不过写法不一样,且不管条件满不满足都会先执行一遍 do 后面 重复执行的代码,至少执行一遍

  示例 2 ——利用 confirm() 打印语句:

do {
   // 把 改变自身 和 执行代码变成一句话了
    var res = confirm('你爱不爱我 ? ')
} while (res === false) // 只要用户点击的取消, 就再执行一遍 do

  剖析示例 2 的代码:
    confirm() 打印语句的返回值是一个布尔值,如果你点击的是确定, 那么就是 true,如果你点击的是取消, 那么就是 false;
    不管条件判断, 先弹出一个选择框,只要用户点击的不是 true,就再次执行重复执行的代码, 再次弹出一个选择框,直到用户选择了 true, 就不再执行代码。

7、forEach( ) 循环

  功能:循环遍历数组中的每个数据,并对数据进行运算,改变原数组;
  参数:回调函数;
  返回值:无
  语法:forEach( 回调函数 )
  注意: forEach() 对于空数组是不会执行回调函数的。
  示例:

var arr = [5, 12, 18, 19, 20, 90]; 
var newArr = arr.forEach((item, index, currArr) => {
    // if(index == 2) {
    //     continue; 
    //     // 不能使用 continue,
    //     // 会报错:Illegal continue statement: no surrounding iteration statement(非法的continue语句:没有周围的迭代语句)
    //     // 想要实现 continue的效果,可以使用 return;
    // }
    if(index == 4) {
        // break; // 不能使用break,报错:Uncaught SyntaxError: Illegal break statement(非法break语句)
        return; // 这个return 不能结束循环,只能结束当前循环,与 continue 的效果一样;
    }
    console.log('item', item);
    console.log('index', index, 'index 类型', typeof index);
    console.log('currArr', currArr);
});
console.log('newArr', newArr); 
console.log(arr);     // 打印原数组 [6, 13, 19, 20, 21, 91]
  • 使用 continue 时:
    在这里插入图片描述
  • 使用 break 时:
    在这里插入图片描述
  • 使用 return 时:
    在这里插入图片描述
    如图所示:

forEach() 循环不能使用 break; 不能使用 continue,想要实现 continue 的效果可以使用
return 替代;

8、map( ) 循环

  功能:循环遍历数组中的每个数据,并对数据进行运算,不改变原数组,返回一个与原数组相同 length 的新数组
  参数:回调函数;
  返回值:新的数组
  语法:map( 回调函数 )
  注意: map() 不会对空数组进行检测。
  注意: map() 不会改变原始数组。
  示例:

var arr = [5, 12, 18, 19, 20, 90]; 
var newArr = arr.map((item, index, currArr) => {
    // if(index == 2) {
        // continue; 
    //     // 不能使用 continue,
    //     // 会报错:Illegal continue statement: no surrounding iteration statement(非法的continue语句:没有周围的迭代语句)
    //     // 想要实现 continue的效果,可以使用 return;
    // }
    if(index == 4) {
        // break; // 不能使用break,报错:Uncaught SyntaxError: Illegal break statement(非法break语句)
        return 321; // 这个return 也不是结束循环,只是在满足当前条件时,给map循环返回值的新数组中加入此返回值,效果也和continue 类似;
    }
    console.log('item', item);
    console.log('index', index, 'index 类型', typeof index);
    console.log('currArr', currArr);
    return item+1;
});
console.log('newArr', newArr);    // 打印返回值 [6, 13, 19, 20, 21, 91] 
console.log(arr);     // 打印原数组 [5, 12, 18, 19, 20, 90]

map() 循环与 forEach() 循环在使用 break、continue 的效果一样,在此便不做多演示了,但在使用 return 时却有不同,因为 map() 循环是通过 return xxx 来返回一个新的数组的;
如图所示:
在这里插入图片描述

9、filter( ) 循环

  功能:检测过滤数组数据,并返回符合条件的所有数据的新数组,不改变原数组;
  参数:回调函数;
  返回值:新的数组;
  语法:filter( 回调函数 )
  注意: filter() 不会对空数组进行检测。
  注意: filter() 不会改变原始数组。
  示例:

var arr = [5, 12, 18, 19, 20, 90]; 
var newArr = arr.filter((item, index, currArr) => {
    // if(index == 2) {
    //     continue; 
    //     // 不能使用 continue,
    //     // 会报错:Illegal continue statement: no surrounding iteration statement(非法的continue语句:没有周围的迭代语句)
    //     // 想要实现 continue的效果,可以使用 return;
    // }
    if(index == 4) {
        // break; // 不能使用break,报错:Uncaught SyntaxError: Illegal break statement(非法break语句)
        return; // 这个return 不能结束循环,只能结束当前循环,与 continue 的效果一样;
    }
    console.log('item', item);
    console.log('index', index, 'index 类型', typeof index);
    console.log('currArr', currArr);
    return item >= 18;
});
console.log('newArr', newArr);     // 打印返回值 [18, 19, 90]
console.log(arr);    // 打印原数组 [5, 12, 18, 19, 20, 90]

在这里插入图片描述

在此,还需要注意一点: 工作中通常后端返回的数组并不是我们想要的,可能我们需要重组一下数据,那么就经常使用到 map或者
filter方法; 如:

  • 假定objArr 为后端返回的数据,但是我们可能需要在页面上自定义一个字段为 age,且这个自定义字段需要在某些条件下,那么在这里我们就可能会这样写:
let objArr = [
     { name: '小花', type: ''},
     { name: '大黄', type: 'dog'} 
];  
let newArr = objArr.map( item => {
	 if(item.type) {
	     item.age = 24;
	     return item;
	 } 
}); 
console.log('newArr', newArr); 
for(let i = 0; i < newArr.length; i++) {
	console.log(newArr[i].age); 
}

但是报错了!!! (抓狂)
在这里插入图片描述
为什么?(抓狂……)

  1. 这是因为 map() 循环是将原有数组“拷贝”一份成为一个新数组,什么意思?意思就是 map() 循环返回的新数组和原数组的长度 length 是一样的,所以当使用条件判断时,不满足的那一项会直接返回undefinedundefined当然而然的会找不到取值的字段名了。
  2. filter() 循环则不同,filter() 循环是将符合条件的返回出去形成一个新的数组,自然而然的能够取到值;所以只需要将 map 改成 filter即可解决报错问题;
    在这里插入图片描述
  3. 当然还有一个方法解决这个报错问题,就是将 return item 移到 if 的外层,这个时候我们需要考虑的就是一个数据的问题,看你的需求是想要什么数据,filter() 是通过条件判断过滤后的数据问题,而
    map() 则是将原数据改造成你想要的数据问题(length不变)。
    在这里插入图片描述
    其实这个问题,在这几个方法的功能介绍里面已经用红色字体标出来。不知道小伙伴们有没有意识到~~~~~~~~

另外:请看这个案例

let list = []
for (let i = 0; i < 3; i++) {
    let item = {
        a: 1,
        b: 2,
    }
    list.push(item)
}
console.log("list", list);

let arr = list.map( (item, index) => {
    if(index == 2){
        item.is = true;
    }
    return item;
})
console.log('arr', arr);
// let newarr = []
let newarr = arr.filter( item => {
    let obj = {}
    if(item.is) {
        obj.c = item.a;
        // newarr.push(obj);
        return obj;
    }
})
console.log('newarr', newarr);

打印结果如图所示:
在这里插入图片描述
是不是感觉到很奇怪,最终newarr的结果不是[{c: 1}],这里还是和 filter这个方法有关,filter 方法是在原数组中筛选过滤出符合条件返回一个新的数组,意思简单点就是说你这个新数组的每一项必须是原数组中存在的。

当然,有的时候我们需要重组数据,且把里面的键名换掉,我们可以这么做:定义一个空数组,然后在符合条件的时候把重组的数据push到空数组里面即可;

let list = []
for (let i = 0; i < 3; i++) {
    let item = {
        a: 1,
        b: 2,
    }
    list.push(item)
}
console.log("list", list);

let arr = list.map( (item, index) => {
    if(index == 2){
        item.is = true;
    }
    return item;
})
console.log('arr', arr);
let newarr = [] // 在这里定义一个空数组
arr.map( item => {
    let obj = {}
    if(item.is) {
        obj.c = item.a; // 然后在符合条件时,把值push到空数组里面去
        newarr.push(obj);
    }
})
console.log('newarr', newarr);

结果如图所示:
在这里插入图片描述

 forEach( )、map( )、filter( ) 总结

  三者的相同点:
    1)参数都是回调函数;
    2)回调函数的参数也是一样的,item 参数代表数组中的元素,index 参数是代表下标,arr是数组;
    3)三者都是遍历(即循环)数组。
  三者的不同点:
    1)forEach( ) 把原始数组的元素内容进行修改;
    2)map( ) 原始数组不变,产生一个新的数组,新的数组是原始数组进行运算(加工)后的映射(也可以理解成为拷贝)的结果;
    3)filter( ) 原始数组不变,过滤,把原始数组中每个元素满足条件的元素(是原数组中已存在的)挑出来,放在一个新的数组里。


附送小案例:九九乘法表

  利用 for 循环的循环嵌套
  效果图如下:
九九乘法表
  具体实现代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        span{
            display: inline-block;
            width: 100px;
            height: 50px;
            border: 1px solid #000;
            margin:2px 2px;
            text-align: center;
            line-height: 50px;
        }
    </style>
</head>
<body>
    <script>
        for (var n = 9; n >= 1; n--){
            for (var i = 9; i >= n; i--){
                document.write( '<span>' + n + '*' + i + '=' + n * i + '&nbsp; </span>')
            }   
            document.write('<br>')        
        }
    </script>
</body>
</html>

如有不足之处,望大家多多指点,谢谢!

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhuangvi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值