js使用for...of遍歷對(duì)象
雖然普通對(duì)象默認(rèn)不支持 for...of,但有多種方法可以實(shí)現(xiàn):
1.使用 Object 的輔助方法
遍歷鍵名 (keys)
const obj = { a: 1, b: 2, c: 3 };
// 方法1: Object.keys()
for (const key of Object.keys(obj)) {
console.log(key); // 'a', 'b', 'c'
console.log(obj[key]); // 1, 2, 3
}
// 方法2: 使用數(shù)組的解構(gòu)和循環(huán)
for (const key of Object.keys(obj)) {
const value = obj[key];
console.log(key, value);
}
遍歷值 (values)
const obj = { a: 1, b: 2, c: 3 };
for (const value of Object.values(obj)) {
console.log(value); // 1, 2, 3
}
遍歷鍵值對(duì) (entries)
const obj = { a: 1, b: 2, c: 3 };
// 方法1: 使用數(shù)組解構(gòu)
for (const [key, value] of Object.entries(obj)) {
console.log(key, value); // 'a' 1, 'b' 2, 'c' 3
}
// 方法2: 不使用解構(gòu)
for (const entry of Object.entries(obj)) {
const key = entry[0];
const value = entry[1];
console.log(key, value);
}
2.使對(duì)象本身可迭代 (實(shí)現(xiàn) Symbol.iterator)
基本實(shí)現(xiàn)
const obj = {
name: 'John',
age: 30,
city: 'New York',
// 添加 Symbol.iterator 方法
[Symbol.iterator]: function* () {
// 遍歷自身屬性
for (const key of Object.keys(this)) {
yield [key, this[key]];
}
}
};
// 現(xiàn)在可以用 for...of 直接遍歷
for (const [key, value] of obj) {
console.log(`${key}: ${value}`);
}
// 輸出:
// name: John
// age: 30
// city: New York
只返回值的迭代器
const obj = {
a: 1,
b: 2,
c: 3,
[Symbol.iterator]: function* () {
for (const key of Object.keys(this)) {
yield this[key];
}
}
};
for (const value of obj) {
console.log(value); // 1, 2, 3
}
3.自定義迭代行為
按特定順序迭代
const user = {
firstName: 'John',
lastName: 'Doe',
age: 30,
email: 'john@example.com',
[Symbol.iterator]: function* () {
// 自定義迭代順序
yield ['姓名', `${this.firstName} ${this.lastName}`];
yield ['年齡', this.age];
yield ['郵箱', this.email];
}
};
for (const [label, value] of user) {
console.log(`${label}: ${value}`);
}
// 輸出:
// 姓名: John Doe
// 年齡: 30
// 郵箱: john@example.com
只迭代特定屬性
const product = {
id: 1,
name: 'Laptop',
price: 999.99,
category: 'Electronics',
inStock: true,
[Symbol.iterator]: function* () {
// 只迭代非布爾值的屬性
const keys = Object.keys(this);
for (const key of keys) {
if (typeof this[key] !== 'boolean') {
yield [key, this[key]];
}
}
}
};
for (const [key, value] of product) {
console.log(`${key}: ${value}`);
}
// 輸出:
// id: 1
// name: Laptop
// price: 999.99
// category: Electronics
4.類(lèi)實(shí)例的可迭代性
class UserCollection {
constructor() {
this.users = [];
}
add(user) {
this.users.push(user);
}
// 使實(shí)例可迭代
*[Symbol.iterator]() {
for (const user of this.users) {
yield user;
}
}
// 或者返回鍵值對(duì)
*entries() {
for (let i = 0; i < this.users.length; i++) {
yield [i, this.users[i]];
}
}
}
const collection = new UserCollection();
collection.add({ name: 'Alice', age: 25 });
collection.add({ name: 'Bob', age: 30 });
// 遍歷用戶(hù)
for (const user of collection) {
console.log(user.name, user.age);
}
// 遍歷帶索引的用戶(hù)
for (const [index, user] of collection.entries()) {
console.log(index, user.name);
}
5.使用生成器函數(shù)
function* objectEntries(obj) {
for (const key of Object.keys(obj)) {
yield [key, obj[key]];
}
}
const obj = { x: 10, y: 20, z: 30 };
for (const [key, value] of objectEntries(obj)) {
console.log(key, value);
}
6.實(shí)際應(yīng)用場(chǎng)景
場(chǎng)景1:遍歷配置對(duì)象
const config = {
apiUrl: 'https://api.example.com',
timeout: 5000,
retries: 3,
debug: false
};
// 配置迭代器
config[Symbol.iterator] = function* () {
const keys = Object.keys(this).sort(); // 按字母排序
for (const key of keys) {
yield { key, value: this[key] };
}
};
for (const { key, value } of config) {
if (typeof value !== 'boolean') { // 過(guò)濾布爾值
console.log(`配置 ${key} = ${value}`);
}
}
場(chǎng)景2:處理嵌套對(duì)象
const company = {
name: 'TechCorp',
departments: {
engineering: { employees: 50, budget: 1000000 },
sales: { employees: 20, budget: 500000 },
marketing: { employees: 15, budget: 300000 }
}
};
// 扁平化迭代器
company[Symbol.iterator] = function* () {
yield ['公司名稱(chēng)', this.name];
for (const [dept, info] of Object.entries(this.departments)) {
yield [`${dept}部門(mén)人數(shù)`, info.employees];
yield [`${dept}部門(mén)預(yù)算`, info.budget];
}
};
for (const [label, value] of company) {
console.log(`${label}: ${value}`);
}
7.性能考慮
const obj = {};
// 創(chuàng)建一個(gè)大對(duì)象
for (let i = 0; i < 1000000; i++) {
obj[`key${i}`] = i;
}
// 測(cè)試不同方法的性能
console.time('Object.keys + for...of');
for (const key of Object.keys(obj)) {
const value = obj[key];
}
console.timeEnd('Object.keys + for...of');
console.time('Object.entries + for...of');
for (const [key, value] of Object.entries(obj)) {
// 直接有值
}
console.timeEnd('Object.entries + for...of');
console.time('for...in');
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
}
}
console.timeEnd('for...in');
8.實(shí)用工具函數(shù)
// 創(chuàng)建可迭代對(duì)象的工具函數(shù)
function makeIterable(obj, options = {}) {
const {
exclude = [], // 排除的屬性
includeOnly = null, // 只包含的屬性
sortKeys = false, // 是否按鍵排序
valueOnly = false // 只返回值
} = options;
const iterable = { ...obj };
iterable[Symbol.iterator] = function* () {
let keys = Object.keys(this);
// 過(guò)濾
if (exclude.length) {
keys = keys.filter(key => !exclude.includes(key));
}
if (includeOnly) {
keys = keys.filter(key => includeOnly.includes(key));
}
// 排序
if (sortKeys) {
keys.sort();
}
// 迭代
for (const key of keys) {
if (valueOnly) {
yield this[key];
} else {
yield [key, this[key]];
}
}
};
return iterable;
}
// 使用示例
const data = { a: 1, b: 2, c: 3, d: 4, e: 5 };
const iterableData = makeIterable(data, {
exclude: ['e'],
sortKeys: true
});
for (const [key, value] of iterableData) {
console.log(key, value); // a 1, b 2, c 3, d 4
}
總結(jié)
- 最簡(jiǎn)單的方法:使用
Object.keys()、Object.values()或Object.entries() - 需要直接迭代對(duì)象:實(shí)現(xiàn)
Symbol.iterator方法 - 需要自定義迭代邏輯:使用生成器函數(shù)
- 考慮性能:
Object.entries()+for...of通常是性能和可讀性的最佳平衡
// 推薦的最佳實(shí)踐
const obj = { a: 1, b: 2, c: 3 };
// 1. 只需要鍵或值
for (const key of Object.keys(obj)) { }
for (const value of Object.values(obj)) { }
// 2. 需要鍵值對(duì)
for (const [key, value] of Object.entries(obj)) { }
// 3. 需要直接迭代對(duì)象(添加迭代器)
obj[Symbol.iterator] = function* () {
for (const [key, value] of Object.entries(this)) {
yield { key, value };
}
};
到此這篇關(guān)于js使用for...of遍歷對(duì)象的文章就介紹到這了,更多相關(guān)js for of遍歷對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
BootStrap 模態(tài)框?qū)崿F(xiàn)刷新網(wǎng)頁(yè)并關(guān)閉功能
這篇文章主要介紹了BootStrap 模態(tài)框?qū)崿F(xiàn)刷新網(wǎng)頁(yè)并關(guān)閉的功能,實(shí)現(xiàn)方法簡(jiǎn)單易懂,需要的朋友可以參考下2017-01-01
JS大坑之19位數(shù)的Number型精度丟失問(wèn)題詳解
這篇文章主要介紹了JS大坑之19位數(shù)的Number型精度丟失問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
js實(shí)現(xiàn)百度聯(lián)盟中一款不錯(cuò)的圖片切換效果完整實(shí)例
這篇文章主要介紹了js實(shí)現(xiàn)百度聯(lián)盟中一款不錯(cuò)的圖片切換效果的方法,以完整實(shí)例形式分析了javascript操作圖片切換的技巧,需要的朋友可以參考下2015-03-03
原生js三級(jí)聯(lián)動(dòng)的簡(jiǎn)單實(shí)現(xiàn)代碼
下面小編就為大家?guī)?lái)一篇原生js三級(jí)聯(lián)動(dòng)的簡(jiǎn)單實(shí)現(xiàn)代碼。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-06-06
JavaScript必知必會(huì)(三) String .的方法來(lái)自何方
這篇文章主要介紹了JavaScript必知必會(huì)(三) String .的方法來(lái)自何方的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下2016-06-06
js+html5實(shí)現(xiàn)可在手機(jī)上玩的拼圖游戲
這篇文章主要介紹了js+html5實(shí)現(xiàn)可在手機(jī)上玩的拼圖游戲,涉及javascript結(jié)合html5進(jìn)行圖形操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07

