js for...in循环和for...of循环

js for…in循环和for…of循环

for...in循环和for...of循环结合ES6新增的方法Object.keys()/Object.values()/Object.entries(),可以以自己想要的方式遍历对象,两者结合使用非常nice

for…in循环

for...in是ES5的标准,该方法遍历的是对象的属性名称(key:键名)。一个Array对象也是一个对象,数组中的每个元素的索引被视为属性名称,所以在使用for...in遍历Array时,拿到的是每个元素索引

注意:Object.keys()返回的是一个数组,对这个数组进行for...in循环,也会拿到数组的原型链上的属性,这点需要注意

  • 一般用于遍历对象自身的和继承的可枚举属性。以及对象从构造函数原型中继承的属性。对于每个不同的属性,语句都会被执行。
  • 不建议使用for...in遍历数组,因为输出的顺序是不固定的。
  • 如果迭代的对象的变量值是null或者undefined, for...in不执行循环体,建议在使用for...in循环之前,先检查该对象的值是不是null或者undefined
  • for…in 语句以原始插入顺序迭代对象的可枚举属性(只能迭代出可枚举的属性,可枚举属性【js自定义属性】/不可枚举属性【对象的内置属性】,如数组的length就是一个内置属性,所以for…in遍历不出来】)。
  • for…in的原理是: Object.keys():返回给定对象所有可枚举属性的字符串数组

for...in循环数组

let arr = [1, 2, 3]
arr.__proto__.name = 'jerry'

for (let i in arr) {
  console.log(i)    // 0, 1, 2, name
}

for (let i in Object.keys(arr)) {
  console.log(i)    // 0, 1, 2, name
}

for (let i = 0; i < arr.length; i++) {
  console.log(i)    // 0, 1, 2
};

for...in循环对象

let obj = {a: 'aaa', b: 'bbb', c: 'ccc'}
obj.__proto__.name = 'jerry'

for (let i in obj) {
  console.log(i)    // a, b, c, name
}

for (let i in Object.keys(obj)) {
  console.log(i)    // 0, 1, 2, name
}

for...in循环字符串

如果Object.keys()传入的是一个字符串,对Object.keys()的结果进行for...in循环,不会获取原型链上的属性

let str = 'abcde'
str.__proto__.age = 18
for (let i in str) {
  console.log(i)    // 0, 1, 2, 3, 4, age
}

for (let i in Object.keys(str)) {
  console.log(i)    // 0, 1, 2, 3, 4  // 这里没有age属性
}

for (let i = 0; i < str.length; i++) {
  console.log(i)    // 0, 1, 2, 3, 4
};

for...of循环

for...ofES6的标准,该方法遍历的是对象的属性所对应的值(value:键值)。所以它用来遍历数组时得到每个元素的值

  • for…of语句在可迭代对象(包括 ArrayStringSetMapTypedArrayargumentsGeneratorsDOM collection对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
  • for…of语句遍历可迭代对象定义要迭代的数据(非自定义属性)
  • for…of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象、Generator 对象,以及字符串。

for...of循环数组

let arr1 = [10, 20, 30];
for (let value of arr1) {
    console.log(value);
}
// 10
// 20
// 30

// 我们可以使用const来替代let,这样它就变成了在循环里的不可修改的静态变量。
let arr2 = [100, 200, 300];

for (const value of arr2) {
    console.log(value);
}
// 100
// 200
// 300

for...of循环字符串

let str1 = "abcde";
for (let value of str1) {
    console.log(value);
}
// a
// b
// c
// d
// e

for...of循环Set

 let set1 = new Set([1, 1, 2, 2, 3, 3]);

for (let value of set1) {
    console.log(value);
}
// 1
// 2
// 3

for...of循环Map

let map1 = new Map([["a", 1], ["b", 2], ["c", 3]]);

for (let [key, value] of map1) {
    console.log(key, value);
}
// 'a' 1
// 'b' 2
// 'c' 3

for (let entry of map1) {
    console.log(entry);
}
// [a, 1]
// [b, 2]
// [c, 3]

for...of循环类型化数组(TypedArray

let tArr = new Uint8Array([0x00, 0xff]);

for (let value of tArr) {
    console.log(value);
}
// 0
// 255

for...of循环arguments

function func() {
    for (let arg of arguments) {
        console.log(arg);
    }
}

func(1, 2, 3)
// 1
// 2
// 3

for...of循环generator

function* gen() { // a generator function
    yield 1;
    yield 2;
    yield 3;
}
for (let n of gen()) {
    console.log(n);
}
// 1
// 2
// 3

function* fibonacci() { // a generator function
    let [prev, curr] = [0, 1];
    while (true) {
        [prev, curr] = [curr, prev + curr];
        yield curr;
    }
}

for (let n of fibonacci()) {
    console.log(n);
    // truncate the sequence at 100
    if (n >= 100) {
        break;
    }
}
// 1
// 2
// 3
// 5
// 8
// 13
// 21
// 34
// 55
// 89
// 144

for...of循环DOM collection

let articleParagraphs = document.querySelectorAll("article > p");

for (let paragraph of articleParagraphs) {
    paragraph.classList.add("read");
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com