关于 for...in
for...in
for...in
语句以任意顺序迭代一个对象的除 Symbol 以外的可枚举属性,包括继承的可枚举属性。
for in 不应该用于迭代一个关注索引顺序的 Array,因为它会把索引顺序的错误暴露给用户。
另外,for in 也不建议用于迭代数组。
定义一个 animal 和 rabbit 对象,rabbit 原型为 animal 。
let animal = {
eats: true,
}
let rabbit = {
jumps: true,
__proto__: animal,
}
for...in
会迭代继承的属性
for (let i in rabbit) {
console.log(i)
}
//jumps eats
怎么才能遍历 rabbit 自己的属性?
1. 使用 Object.keys(obj)
仅返回 rabbit 对象自己的可枚举属性。
Object.keys(rabbit)
这些属性的顺序与手动遍历该对象属性时的一致。
2. 使用 obj.hasOwnProperty(key)
过滤
for (let i in rabbit) {
if (rabbit.hasOwnProperty(i)) {
console.log(i)
}
}
// jumps
3. getOwnPropertyNames
for (let i in rabbit) {
console.log(Object.getOwnPropertyNames(rabbit))
}
// [ 'jumps']
但这样会把不可枚举对象也返回。
例如:
下边的代码定义了一个对象 o,属性 a 是 enumerable
的,b 不是。
// 创建一个新对象
var o = { a: 'cat' }
// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, 'b', {
value: 'dog',
writable: true,
enumerable: false,
configurable: true,
})
如果现在还要使用 Object.getOwnPropertyNames(obj)
,就会把不可枚举的属性也返回。
console.log(Object.getOwnPropertyNames(o))
// [ 'a', 'b' ]
// 这里的 b 是不可枚举的。
再比如:
const arr = ['a', 'b', 'c']
console.log(Object.getOwnPropertyNames(arr))
//['0', '1', '2', 'length']
// 这里的 length 是不可枚举的。
通常我们并不需要返回那些不可枚举的属性,
所以可以使用 Object.prototype.propertyIsEnumerable(prop)
过滤掉不可枚举的属性。
可能你会发现,既然 for...in 会迭代继承的属性, 那为什么 Object.prototype 的属性却没有被遍历呢?
这是因为 Object.prototype
中的属性有 enumerable:false
的标志。
基本包装类型的原型属性是不可枚举的
最后,for...in
是为遍历对象属性而构建的,不建议与数组一起使用。
如果你只要考虑对象本身的属性,而不是它的原型,那么使用 getOwnPropertyNames() 或执行 hasOwnProperty() 来确定某属性是否是对象本身的属性(也能使用 propertyIsEnumerable)。
for...of
for...of
语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
对于 for...of 的循环,可以由 break, throw 或 return 终止。
for...in 与 for...of 的区别
它们之间的主要区别在于它们的迭代方式。
for...in
为了遍历一个对象的所有键(key),语句以任意顺序迭代对象的可枚举属性。
for...of
语句遍历可迭代对象定义要迭代的数据。
并且,不建议使用 for...in 遍历数组。
👇 如果你有好的想法,请一起完善吧