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...of
是ES6
的标准,该方法遍历的是对象的属性所对应的值(value
:键值)。所以它用来遍历数组时得到每个元素的值
for…of
语句在可迭代对象(包括Array
,String
,Set
,Map
,TypedArray
,arguments
,Generators
,DOM 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