js让for of也可以遍历对象

本文介绍了如何使用forof遍历JavaScript对象,并通过添加迭代器属性使其可用。同时,展示了如何自定义数组的迭代器方法,以便于控制遍历顺序。

首先我们要明白一个概念,for of能遍历的元素,只要是元素上有迭代器这个属性就可以遍历
比如说 我们的数组
在这里插入图片描述
我们的对象上 就没有这个属性, 所以就不能进行 for of遍历循环, 如果想要我们的对象可以用for of循环,那么再对象上 加上这个 迭代器属性就行了

   // 这里 要用let 因为下面我们要给属性加上一个 迭代器
   let obj = {
    0: 1,
    1: 2,
    2: 3,
    length: 3    // 需要给对象上加上 length,因为我们用的是数组的迭代器
   };

   obj[Symbol.iterator] = Array.prototype[Symbol.iterator];
   for(let item of obj) {
    console.log(item, "item");
   }

通过迭代器的概念 我们就解决了 遍历对象乱序的问题了
在这里插入图片描述

同样 我们可以自己修改 数组里面的迭代器方法

let arr = [1, 2, 3, 4, 5];
arr[Symbol.iterator] = function () {
    // 这里的this 代表的是这个数组
    let self = this,
    index = 0;

    return {
        // 迭代器 必须是要有next方法, 拿到结构中的某个值
        // done: false 是迭代器还没有结束循环  done: true 是代表结束循环了
        next() {
            if(index > self.length -1 ) {
                return {
                    done: true,
                    value: undefined
                };
            } 
            // 这里 我们可以让index + 1
            index = index + 2;
            return {
                done: false,
                value: self[index]
            };
        }
    };
}

for(let item of arr) {
    console.log(item, "item");
}

在这里插入图片描述

<think> 我们被要求回答:for of是否可用于遍历对象,以及for of相比for in的区别和优势 根据引用: 引用[1]提到:for-of支持数组和大多数类数组对象(如DOM NodeList),还支持字符串遍历。 引用[2]提到:推荐在循环对象属性的时候使用 for...in,在遍历数组的时候使用 for...offor...in循环出的是key,for...of循环出的是value;for...of不能循环普通的对象(如通过构造函数创造的),需要通过和Object.keys()搭配使用。 引用[3]提到:for...of适用于所有可迭代对象,包括字符串、Map、Set等。 引用[4]提到:遍历对象通常用for...in来遍历对象的键名。 因此,我们可以总结: 1. for...of 不能直接遍历普通对象(即通过字面量或构造函数创建的普通对象),因为普通对象默认不是可迭代的(iterable)。但是,我们可以通过使用Object.keys()、Object.values()或Object.entries()来获取对象的键、值或键值对数组,然后使用for...of遍历这些数组。 2. for...in 主要用于遍历对象的可枚举属性(包括自身属性和继承的可枚举属性,但通常我们只关心自身属性,所以需要配合hasOwnProperty()使用)。 区别和优势: - 遍历内容: for...in 遍历的是对象的键(key),而 for...of 遍历的是可迭代对象的值(value)。 - 适用范围: for...in 适用于遍历对象(普通对象)的属性,但也可以用于数组(不过不推荐,因为会遍历到数组的非数字键和原型链上的属性)。 for...of 适用于遍历可迭代对象(Array, Map, Set, String, TypedArray, arguments 等),但不能直接遍历普通对象。 - 对循环控制语句的支持: for...of 可以正确响应 break, continue 和 return 语句(在函数内部使用),而 forEach 方法则不能直接跳出循环(除非通过异常)。 - 遍历顺序: for...in 循环的遍历顺序不一定按照对象的属性顺序(依赖于具体实现),而 for...of 遍历数组等可迭代对象时,会按照元素的顺序。 因此,回答用户的问题: for of 不能直接遍历普通对象,因为普通对象不是可迭代的(除非我们将其转换为可迭代对象,或者使用Object的方法得到可迭代的数组形式)。而for in可以遍历对象的键。 优势: - for...of遍历数组时更安全,不会遍历到非数字键和原型链上的属性(而for...in会)。 - for...of 提供了更简洁的语法来直接获取值。 - for...of 支持各种可迭代对象,使得代码更通用。 示例代码: 使用 for...in 遍历对象: ```javascript const obj = {a: 1, b: 2, c: 3}; for (const key in obj) { if (obj.hasOwnProperty(key)) { // 避免遍历到原型链上的属性 console.log(key, obj[key]); } } ``` 使用 for...of 遍历对象的键(通过Object.keys): ```javascript const obj = {a: 1, b: 2, c: 3}; for (const key of Object.keys(obj)) { console.log(key, obj[key]); } ``` 或者直接遍历对象的值: ```javascript for (const value of Object.values(obj)) { console.log(value); } ``` 或者遍历键值对: ```javascript for (const [key, value] of Object.entries(obj)) { console.log(key, value); } ``` 注意:Object.keys(), Object.values(), Object.entries() 返回的都是数组,而数组是可迭代的,所以可以用for...of。 但是,如果对象是通过自定义迭代器实现的,那么就可以直接用for...of遍历。不过,这需要我们在对象上定义Symbol.iterator属性。例如: ```javascript const iterableObj = { data: [1, 2, 3], [Symbol.iterator]() { let index = 0; return { next: () => { if (index < this.data.length) { return { value: this.data[index++], done: false }; } return { done: true }; } }; } }; for (const item of iterableObj) { console.log(item); // 输出1, 2, 3 } ``` 不过,普通对象默认没有定义Symbol.iterator,所以不能直接使用for...of。 结论: - 如果你有一个普通对象,用for...in(注意过滤原型属性)或者配合Object.keys等方法使用for...of。 - 如果你有一个数组、字符串等内置可迭代对象,用for...of更安全方便。 根据要求,我们需要在回答中自然地添加引用标识。由于我们的回答主要基于引用[1][2][3][4],因此可以在相关部分添加引用。 同时,按照指令,我们需要生成相关问题。 </think>### `for...of` 能否遍历对象? **不能直接遍历普通对象**。`for...of` 要求目标必须是可迭代对象(如数组、字符串、Map、Set 等),而普通对象(`{}` 或 `new Object()`)默认不可迭代。若需遍历对象属性,可借助以下方法: ```javascript const obj = { a: 1, b: 2 }; // 方法1:遍历对象的键 for (const key of Object.keys(obj)) { console.log(key); // 输出:'a', 'b' } // 方法2:遍历对象的值 for (const value of Object.values(obj)) { console.log(value); // 输出:1, 2 } // 方法3:遍历键值对 for (const [key, value] of Object.entries(obj)) { console.log(`${key}: ${value}`); // 输出:'a: 1', 'b: 2' } ``` --- ### `for...of` 与 `for...in` 的区别与优势 #### 核心区别 | **特性** | `for...in` | `for...of` | |-------------------|--------------------------------|--------------------------------| | **遍历内容** | 对象的可枚举属性(键) | 可迭代对象的值(值) | | **适用对象** | 普通对象、数组(不推荐) | 数组、字符串、Map、Set 等可迭代对象 | | **原型链属性** | 会遍历继承的属性 | 仅遍历自身元素 | | **循环控制** | 支持 `break`/`continue` | 支持 `break`/`continue`/`return` | | **ES 标准** | ES5 | ES6 | #### `for...of` 的优势 1. **更安全的数组遍历** ```javascript const arr = [1, 2, 3]; arr.customProp = 'foo'; // for...in 会遍历自定义属性(不推荐) for (const key in arr) { console.log(key); // 输出:'0', '1', '2', 'customProp' } // for...of遍历数组元素 for (const value of arr) { console.log(value); // 输出:1, 2, 3 } ``` 2. **支持更多数据结构** 可直接遍历字符串、Map、Set 等: ```javascript // 字符串遍历 for (const char of 'hello') { console.log(char); // 输出:'h', 'e', 'l', 'l', 'o' } // Map 遍历 const map = new Map([['a', 1], ['b', 2]]); for (const [key, value] of map) { console.log(key, value); // 输出:'a' 1, 'b' 2 } ``` 3. **避免意外遍历原型属性** `for...in` 需手动过滤继承属性: ```javascript for (const key in obj) { if (obj.hasOwnProperty(key)) { // 额外检查 console.log(key); } } ``` `for...of` 无需此操作。 4. **性能更优** 在遍历数组时,`for...of` 比 `for...in` 性能更高(因后者需检查原型链)。 --- ### 总结 - **遍历对象属性** → 用 `for...in`(需配合 `hasOwnProperty` 过滤原型属性)或 `Object.keys()` + `for...of`。 - **遍历数组、字符串等可迭代对象** → **优先用 `for...of`**(更安全、简洁、高效)[^1][^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值