for in
它主要用于遍历对象的可枚举属性(包括数组,但不推荐用于数组)
遍历目标:对象的键(Key)
特点:它会遍历对象自身以及原型链上的所有可枚举属性
const person = { name: 'Alice', age: 25, job: 'Engineer' };
for (let key in person) {
console.log(key); // 输出: "name", "age", "job"
console.log(person[key]); // 输出: "Alice", 25, "Engineer"
}
⚠️注意:如果用 for...in 遍历数组,拿到的是数组的下标("0", "1", "2"...)
不推荐用来遍历数组哈。
for in 它会把原型链上的属性也进行遍历
刚刚我们说了:for in 它会遍历对象自身以及原型链上的所有可枚举属性
下面我们举一个例子来说明这种情况。
const user = { name: 'Alice', age: 25 };
// 模拟某个库或同事在原型上加了属性
Object.prototype.extra = '污染属性';
for (const key in user) {
console.log(key);
}
// 输出:
// "name"
// "age"
// "extra" ----> 不是 user 自己的属性;是原型链上的属性
只遍对象自身的可枚举属性(1) 推荐这样遍历对象
Object.keys、Object.entries 只返回对象自身的可枚举属性,不会遍历原型链,所以更稳。
Object.keys 会返回对象自身可枚举属性键名作为数组,如: 'name', 'age'
const user = { name: 'Alice', age: 25 };
// 模拟某个库或同事在原型上加了属性
Object.prototype.extra = '污染属性';
for (const key of Object.keys(user)) {
console.log(key, user[key]);
}
// 输出:这样就不会输出 extra 属性了
// name Alice
// age 25
Object.keys的简单介绍
现代浏览器全部支持,IE9+ 基本可用;兼容性最好。ES5(ES2016年)
Object.keys 会返回对象自身可枚举属性键名作为数组,不会把原型链上的属性带出来。
对数组使用 Object.keys(),返回的是数组下标:Object.keys("AA","BB") → "0", "1"
对字符串使用,返回字符索引:Object.keys("abc") → "0", "1", "2"
数字键会按数值升序排列:Object.keys({10: 'a', 2: 'b', c: 'd'}) → "2", "10", "c"
传入 null 或 undefined 会报错:TypeError
const user = { name: 'Alice', age: 25 };
console.log(Object.keys(user)); // 输出:["name", "age"]
判断对象是否为空
Object.keys({}).length === 0; // true
Object.entries
ES2017(ES8) 就是 2017 年发布的;推荐但要避开很老的浏览器。
只返回对象自身的可枚举属性,不会遍历原型链。
用来把对象转成键值对数组,如:\["name", "Alice", "age", 25]
对数组使用时,键是下标字符串:Object.entries('a', 'b')==> \['0', 'a', '1', 'b' ]
简单说:Object.keys()拿键,Object.values()拿值,Object.entries()同时拿键和值。
const user = { name: 'Alice', age: 25 };
console.log(Object.entries(user));
// [ ['name', 'Alice'], ['age', 25] ]
只遍历对象自身的可枚举属性(2)
// 模拟某个库或同事在原型上加了属性
const user = { name: 'Alice', age: 25 };
// 模拟某个库或同事在原型上加了属性
Object.prototype.extra = '污染属性';
for (const [key, value] of Object.entries(user)) {
console.log(key, value);
}
// name Alice
// age 25
Object.keys和 for...of 的区别
1,for...in会遍历原型链上的属性,Object.keys不会遍历原型链上的属性。
2,for...in返回的是键名,Object.keys返回的是键名组成的数组。
for...of 循环
它是 ES6 (ES2015) 引入的新特性,专门用于遍历可迭代对象。
遍历目标:可迭代对象(如 Array, Map, Set, String, arguments 等)
const colors = ['red', 'green', 'blue'];
for (let color of colors) {
console.log(color); // 输出: "red", "green", "blue"
}
// 遍历字符串
for (let char of 'Hello') {
console.log(char); // 输出: "H", "e", "l", "l", "o"
}
总结 for in 和 for...of
for in 主要用来遍历对象。虽然可以遍历数组,但是不推荐。
for...of 主要用来遍历数组,当然也可以是:Array, Map, Set, String, arguments
什么是可枚举属性
JavaScript 里每个属性都有一个内部标记 enumerable
enumerable: true 可枚举
enumerable: false:不可枚举
enumerable /ɪˈnjuːmərəbl/拆成四个音节来读:in-nu-mer-a-ble 因-纽-么-若-波
通过 Object.defineProperty 创建时,默认是不可枚举的
const obj = { name: 'Alice' };
Object.defineProperty(obj, 'id', {
value: '123',
enumerable: false
});
// name属性是可枚举,id是不可枚举的
console.log(obj)
怎么去判断是否是可枚举属性呢 ?
通过 Object.getOwnPropertyDescriptor 来进行判断
const obj = { name: 'Alice' };
Object.defineProperty(obj, 'id', {
value: '123',
enumerable: false
});
console.log(Object.getOwnPropertyDescriptor(obj, 'name').enumerable); // true
console.log(Object.getOwnPropertyDescriptor(obj, 'id').enumerable); // false