JS 循环大全 最强详解

目录

什么是遍历器?什么是可迭代对象?什么是迭代?什么是可枚举属性?

for 循环

while 循环

do... while 循环

for ... in 循环

for ... of 循环

.forEach 循环 

.map() 循环

最后,罗列了几个问题点:


什么是遍历器?什么是可迭代对象?什么是迭代?什么是可枚举属性?

遍历器(Iterator)的诞生:

最初 JS 里用来表示“集合”的数据结构,有数组( Array )和对象( Object ),但在 ES6 中添加了 Map 和 Set 。这样就有了四种数据集合,用户还可以组合使用它们,定义自己的数据结构,比如数组的成员是 Map , Map 的成员是对象。这样就需要一种统一的接口机制,来处理所有不同的数据结构。

就这样 遍历器(Iterator)的诞生了

遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。

遍历器(Iterator) 的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是 ES6 创造了一种新的遍历命令 for...of 循环,Iterator 接口主要供 for...of 消费。

可迭代对象:

一种数据结构只要部署了 Iterator 接口,我们就称这种数据结构是“可遍历的”(iterable)。

ES6 规定,默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性,或者说,一个数据结构只要具有 Symbol.iterator 属性,就可以认为是“可遍历的”(iterable)。(见图 img-1)。原生具备 Iterator 接口的数据结构如下。【Array, Map, Set, String, TypedArray, 函数的 arguments 对象, NodeList 对象】

迭代

迭代是递归的一种特殊形式,是迭代器提供的一种方法,默认情况下是按照一定顺序逐个访问数据结构成员。迭代也是一种遍历行为。

可枚举属性:

在JavaScript中,对象的属性分为可枚举和不可枚举之分,它们是由属性的 enumerable 值决定的。可枚举性决定了这个属性能否被 for…in 查找遍历到。

迭代器:

Symbol.iterator 属性本身是一个函数,就是当前数据结构默认的遍历器生成函数。执行这个函数,就会返回一个.next() 遍历器

每一次调用 next 方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含 value 和 done 两个属性的对象。其中, value 属性是当前成员的值, done 属性是一个布尔值,表示遍历是否结束。看下面代码并见图 img-2

Iterator 的遍历过程:

(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。

(2)第一次调用指针对象的 next 方法,可以将指针指向数据结构的第一个成员。

(3)第二次调用指针对象的 next 方法,指针就指向数据结构的第二个成员。

(4)不断调用指针对象的 next 方法,直到它指向数据结构的结束位置。

arrayList: [
    {name: '小明', age: 12},
    {name: '小花', age: 10},
    {name: '小黑', age: 14}
]

const iterator = this.arrayList[Symbol.iterator]();
console.log('iterator =>', iterator)

// 模拟循环
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())

JS 循环大全 最强详解_第1张图片 img-1 JS 循环大全 最强详解_第2张图片 img-2

for 循环

for 是最早出现的循环,也是最常用的,它是一种循环机制,能够满足大部分的遍历。主要是依靠角标来获取数组内成员。

JS 循环大全 最强详解_第3张图片

位置 作用 详解 是否必要
初始化 循环变量 只在循环开始前执行一次,后面轮循环时就不会被执行了 可省略(见 for 例子2)
定义循环条件

每轮循环都会执行条件判断,结果为 true,接着执行下一轮循环

直到为 false 时结束整个 for 循环。

可省略(见 for 例子3)
更新初始化的变量

当处于这个时间节点时(当前这轮循环结束后,

进入下一轮循环条件判断之前)

执行的 更新初始化变量(这句话应该能看的懂吧!)

可省略(见 for 例子4)
循环执行的代码块

简单介绍(注意):

适用于复杂的处理

再循环中 可以利用角标来删除元素,追加元素,修改元素值

它是一种循环机制

三个语句都可省略,但【;】号必须要有

循环体中可以使用 break(跳出循环)和 continue(阻止当前轮循环继续往下执行,并且进入下一轮循环)

可以循环 数组、对象(见 for例子5)、字符串

当省略②时:别忘记在循环体内使用 break,否则循环永远不会结束!

当省略③时:别忘记在循环体内更新 ①,否则可能会造成永远不会结束!

// 语法 结构 
for (语句 1; 语句 2; 语句 3) { 
  循环 执行的代码块...
}

// for 例子 1 
for (let i=0; i<3; i++) {
  console.log(i)
}
// for 例子2
// 可省略语句1(比如在循环开始前已经设置了值时)
// 适用场景,i的初始化值是动态获取的
let i = 2;
for (; i<3; i++) { 
    console.log(i)
}
// for 例子3
// 可省略语句2,省略后必须在循环内提供 break 让循环结束。
// 否则循环就无法停下来。这样有可能令浏览器崩溃。
for (let i=0; ; i++) {
    console.log(i)
    if(i == 5){
        break ;
    }
}
// for 例子4
// 可省略语句3,写在循环体内。
for (let i=0; i<3; ) {
    console.log(i)
    i++
}
// for 例子5
// 三个语句都省略
let i = 0; // 语句1,设置在外面
for (; ; ) {
    if(i == 5){
        break ; // 语句2,添加条件,避免出现永久循环
    }
    console.log(i)
    i ++; // 语句3,设置在里面
}
// for 例子6
// 通过使用 ES6中新增的 Object.keys() 方法 帮助for可以循环对象
let obj = {
  name:'小明'
  age: 12,
}
let keys = Object.keys(obj);
for (let i = 0; i < keys.length; i++){
  console.log(obj[keys[i]])
}

记住这种两种写法特点,在进行一些特殊情况时的数据处理会对你很有用

// for 特殊写法
// 不知道这种写法,同学们有没有见过
// 将获取数组长度的竟然放在了语句1里面
// 我在文章的上面讲过,语句1,执行一次对吧
// 那么这种写法,它的好处以及坏处,大家看打印结果,你就会明白的
let arr = ['01','02','03'];
for(let i = 0, len = arr.length; i

while 循环

while 循环只要指定条件结果为 true,循环就可以一直执行代码块。

JS 循环大全 最强详解_第4张图片

简单介绍(注意):

别忘记更新条件中所用变量的值,否则循环永远不会结束!

当①结果为true时进入循环

循环体中可以使用 break(跳出循环)

// 语法结构
while (条件){
    需要执行的代码
}

// 该循环永远不会结束,这可能导致浏览器崩溃。
while(true){
    console.log('加菲猫!')
}

const arr = ['1','2',undefined,'3','','4'];
let i = 0;
while(arr[i]){
    console.log(arr[i])
    i = i + 1;
}
// 输出: 1
// 输出: 2

const arr = ['1','2','3','4'];
let i = 0;
while(arr[i]){
    console.log(arr[i])
    i = i + 1;
}
// 输出: 1
// 输出: 2
// 输出: 3
// 输出: 4

do... while 循环

do... while 循环是 while 循环的变体。该循环会在判断条件是否为真之前执行一次代码块,然后如果条件为真的话,就会重复这个循环。

JS 循环大全 最强详解_第5张图片

简单介绍(注意):

它具有 即使条件的结果为 false,也至少循环一次的特点

别忘记更新条件中所用变量的值,否则循环永远不会结束!

循环体中可以使用 break(跳出循环)

// 语法结构
do
{
    需要执行的代码
}
while (条件);
// do while 例子1
const arr = [1,2,3,4];
let i = 0;
let num = 0;
do
{
    num = num + arr[i]; // 数组内成员的和
    i++ ;
}while (arr[i]);

console.log(num) // 10
//数组中的【0,null,false,undefined, 空字符串】 当做false处理
// do while 例子2
const arr = [null,1,2,3,4];
let i = 0;
let num = 0;
do
{
    console.log(arr[i])
    i++ ;
}while (arr[i]);

// 角标 0 的位置,我故意放置了一个 null
// 因为先执行的 do 内的代码块 由(i=0) => 变(i=1)
// 所以当第一次进入 while 条件判断时, i变成了1, (arr[1]) => (1)

for ... in 循环

for ... in 是在 ES5 中新增的,遍历所有可枚举的属性(包括原型上的),最好只用来循环对象。

JS 循环大全 最强详解_第6张图片

简单介绍(注意):

我觉得它的设计初衷就是循环对象,所以推荐大家用它时最好就是遍历对象

用于 遍历对象的所有可枚举属性、字符串、数组(最好不要使用for...in循环数组)

遍历  数组时 语句①为数组的角标,并且它的 index 索引是字符串型数字

遍历 数组时 循环顺序有可能不是按照实际数组的内部顺序,不推荐使用 通过for ... in循环出来的角标

可以使用 break(跳出循环)和 continue(阻止当前轮循环继续往下执行,并且进入下一轮循环)

// 语法结构
for(let 成员 in 对象){
    循环的代码块
}
// for in 例子1
const json = {
    name: '加菲猫',
    sex: '男',
    age: '8',
};
for(let item in json){
    console.log('item =>', item , json[item])
}
// 输出:item => name 加菲猫
// 输出:item => sex 男
// 输出:item => age 8

for ... of 循环

for...of 是在 ES6 中新增的 语句,它遍历一个可迭代的对象(不明白可迭代对象,看文章顶部有关可迭代对象的介绍)

JS 循环大全 最强详解_第7张图片

简单介绍(注意):

用于遍历可迭代对象 以及 字符串

想要在 for ...of 中得到数组的索引,需要使用 array.entries() 方法(见 for of 例子2)

可以使用 break(跳出循环)和 continue(阻止当前轮循环继续往下执行,并且进入下一轮循环

// for of 例子1
const arr = [1,2,3];
let item;
for(item of arr){
    console.log('item =>', item)
}

// 输出:item => 1
// 输出:item => 2
// 输出:item => 3
// for of 例子2
// 使用 entries() 方法后,语句1 在每次遍历中就会得到一个数组,格式如下 下方配有截图
// 输出:index => (2) [0, 1]
// 输出:index => (2) [1, 2]
// 输出:index => (2) [2, 3]

const arr = [1,2,3];
let item,index;
for([index,item] of arr.entries()){
    console.log('index =>', index , 'item =>', item)
}

// 注意,这种情况下,角标在第一个位置,元素在第二个位置
// 输出:index => 0 item => 1
// 输出:index => 1 item => 2
// 输出:index => 2 item => 3

JS 循环大全 最强详解_第8张图片

// for of 例子3
// for of 中使用解构
const arr = [
    {name: '小A', age: 12},
    {name: '小B', age: 10},
    {name: '小C', age: 14},
];
let ages = 0, age = 0;
for({age} of arr){
    ages = ages + age;
}
console.log('总年龄 =>', ages)
// 输出:总年龄 => 36

.forEach 循环 

forEach 是 ES5 提出的,挂载在可迭代对象原型上的方法。forEach是一个遍历器,负责遍历可迭代对象。

JS 循环大全 最强详解_第9张图片

位置 详解 是否必要
当前元素 必须
当前元素的角标。 可省略

当前被遍历的数组对象

可省略
回调函数中的this指向,默认为undefined 可省略

简单介绍(注意):


用于遍历 可迭代对象 以及 字符串

forEach() 对于空数组是不会执行回调函数的。

forEach() 中想要跳出循环 可以使用 try/catch。(见 forEach 例子1)

forEach() 中不建议修改正在遍历的可迭代对象内的元素值,避免出现低级错误。

// 语法结构
array.forEach(function(currentValue, index, arr), thisValue)
// forEach 例子1
try{
    const arr = [1,2,3,4];
    arr.forEach((item,index,arr) => {
        console.log('item =>', item)
        if(item == 2){
            throw new Error('11') // 抛出异常
        }
    })
}catch(e){
    if (e.message !== "11") throw e;
}

console.log('啦啦啦')

// 输出:item => 1
// 输出:item => 2
// 输出:啦啦啦
// forEach 例子2
// 遍历对象
const json = {
    name: '加菲猫',
    age: 10
}
const kyes = Object.keys(json);
console.log('kyes =>', kyes)
kyes.forEach((item)=>{
    console.log(item, json[item])
})

// 输出:kyes => ['name', 'age']
// 输出:name 加菲猫
// 输出:age 10

.map() 循环

.map() 和 forEach 一样都是 ES5 提出的 ,.map() 方法是挂载在 Array 对象的原型上的 。 基本用法跟 forEach 方法类似。

JS 循环大全 最强详解_第10张图片

位置 详解 是否必要
当前元素 必须
当前元素的角标。 可省略

当前被遍历的数组对象

可省略
回调函数中的this指向,默认为undefined 可省略

简单介绍(注意):


.map() 只能遍历 Array对象

.map() 它有返回值(它返回一个新的数组),新数组中的元素 为 原始数组元素 在回调函数内处理后的值。

.map() 不会对空数组进行检测。

.map() 当数组中的值为基本数据类型时不会改变原始数组(当数组内的元素为对象会被改变)。(见 map 例子1)

// 语法结构
array.map(function(currentValue,index,arr), thisValue)
// map 例子1
const arr = [1,2,3];
const hh = arr.map((item, index, arr) =>{
    item = item + 10;
    return item;
})
console.log('hh =>', JSON.parse(JSON.stringify(hh))) // 新数组
console.log('arr =>', JSON.parse(JSON.stringify(arr))) // 原数组


// 输出:hh => [11, 12, 13]
// 输出:arr => [1, 2, 3]
// map 例子2
const arr = [{
    id: 1,
    name: '加菲猫',
},{
    id: 2,
    name: '欧弟',
}];
const home = arr.map((item, index, arr) =>{
    return item.name;
})

/*
home 格式如下:
[
    '加菲猫',
    '欧弟'
]
*/

最后,罗列了几个问题点:

1. for...in 与 for...of 的区别,for in 和 for of 打印 item 输出的分别是什么?

const arr = [1,2,3,4,5]

for(let item in arr)

for(let item of arr)

2. for 循环和 forEach 的本质区别是什么?

你可能感兴趣的:(JS,javascript,es6)