for in
const obj = {
id: 1,
name: "yiliang",
age: 18,
};
for (let key in obj) {
console.log(key + "---" + obj[key]);
}
- 它可与
break、continue和return配合使用
for in 的缺陷
给内置原型 Object.prototype 添加属性/方法,for in 时也是可遍历的。如果重写了内置属性, 例如 toString 之类的函数,大多数现代浏览器都是会打印出来的。但是 for in 不会读取不可枚举属性,如数组的 length 属性。
所以不能依赖于 for in 来获取对象的成员名称,一般会配合 hasOwnProperty 打印对象的键值,没人可以保证运行的代码环境是否被污染过。
for-in 遍历数组的问题?
for-in赋给 index 的值不是实际的数字,而是字符串 “0”、“1”、“2”,此时很可能在无意之间进行字符串算数计算,例如:“2” + 1 == “21”,这给编码过程带来极大的不便。- 作用于数组的 for-in 循环体除了遍历数组元素外,还会遍历自定义属性。举个例子,如果你的数组中有一个可枚举属性 myArray.name,循环将额外执行一次,遍历到名为“name”的索引。就连数组原型链上的属性都能被访问到。
in 操作符
in操作符只要通过对象能访问到属性就返回true。 in 缺陷---属性是继承来的时候,仍然返回 true. 使用delete操作符则可以完全删除实例属性,但不能删除原型链中的属性。
for of
遍历数组:for-in获取索引,for-of获取值
for of, for in 和 forEach, map 的区别
- for in 是遍历对象的。使用 for in 会遍历数组所有的可枚举属性,包括原型。所以for-in 用于遍历对象更好,for in 遍历的是数组的索引(即键名)。for in 用于遍历对象更好
- for of 用于遍历数组更好,只遍历数组的元素值,不遍历数组对象上挂载的属性。
- for of 循环:具有 iterator 接口,就可以用 for of 循环遍历它的成员(属性值)。for of 循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象、Generator 对象,以及字符串。for of 循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。对于普通的对象,for of 结构不能直接使用,会报错,必须部署了 Iterator 接口后才能使用。可以中断循环。
- for in 循环:遍历对象自身的和继承的可枚举的属性, 不能直接获取属性值。可以中断循环。
- forEach: 只能遍历数组,不能中断,没有返回值(或认为返回值是 undefined)。注意: forEach() 对于空数组是不会执行回调函数的
- map: 只能遍历数组,不能中断,返回值是修改后的数组
停止 for 循环
break 可以停止 for in 和 for of 循环, 不能停止 forEach 循环。
foreach 跳出循环
try {
arr.forEach((item, index) => {
if (item === "b") throw new Error("exist");
console.log(item);
});
} catch (e) {
if (e.message == "exist") throw e;
} finally {
console.log("done");
}
程序最后可以终止退出循环,所以使用 try...catch 通过抛出异常的方式来终止程序继续执行是可行。
foreach 不能异步原因
foreach 源码:
// ...
Array.prototype.forEach = function (callback, thisArg) {
var len = O.length >>> 0;
k = 0;
// 7. Repeat, while k < len
while (k < len) {
if (k in O) {
// ...
callback.call(T, kValue, k, O);
}
k++;
}
};
// ...
可以看到代码中有一个 while 循环一直在调用 callback 回调函数,判断这里应该是异步并行调用的,因为我们只是在将 foreach 中的 callback 使用了 async/await 来等待异步返回操作,而本身这个 foreach 并没有使用 async/await 来等待异步返回。
使用 foreach 时其实也就相当于调用了一个封装了 while 或者 for 循环的函数,这个函数本身并没有使用 async/await 来处理异步,所以使用时在回调函数里面加上 async/await 是没有作用的,遍历的方式有很多种,那么我们在需要遍历处理异步的时候,最好还是使用 for 或者 while 来实现,不管是封装一个新的函数,或者是直接使用来遍历都可以避免这个问题。
说一下 for...in 和 for...of 的区别?
for...of 遍历获取的是对象的键值, for...in 获取的是对象的键名; for...in 会遍历对象的整个原型链, 性能非常差不推荐使用,而 for...of 只遍历当前对象不会遍历原型链; 对于数组的遍历,for...in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for...of 只返回数组的下标对应的属性值; 总结:for...in 循环主要是为了遍历对象而生,不适用遍历数组; for....of 循环可以用来遍历数组、类数组对象、字符串、Set、Map 以及 Generator 对象