for和of的区别

for和of是两个完全不同的东西,但又总被人搞混。

最直接的区别是:for...in 遍历的是对象的属性名(key),而 for...of 遍历的是可迭代对象的值(value)。

听起来很简单,但实际用起来,坑就来了。

先说 for...in,它就是为遍历普通对象设计的

想象一个简单的场景,你想看看一个对象里都有什么:

“`javascript

const person = {

name: ‘老王’,

age: 30,

gender: ‘male’

};

for (let key in person) {

console.log(key);

}

// 输出:

// ‘name’

// ‘age’

// ‘gender’

“`

你看,for...inperson 对象的所有属性名(key)都打印出来了。如果你想要拿到对应的值,也很简单,用方括号语法 person[key] 就行。

javascript

for (let key in person) {

console.log(key + ': ' + person[key]);

}

// 输出:

// 'name: 老王'

// 'age: 30'

// 'gender: male'

这看起来很完美,对吧?但是,for...in 有个大问题:它会遍历对象原型链上的可枚举属性。 这是个什么意思呢?

简单来说,JavaScript 中的对象都有一个“后台老板”,就是它的原型(prototype)。如果你给这个“后台老板”添加了属性,那么 for...in 在遍历小弟的时候,也会把老板的属性给带出来。

举个例子:

“`javascript

Object.prototype.sharedProperty = ‘这是所有对象共享的属性’;

const person = {

name: ‘老王’,

age: 30

};

for (let key in person) {

console.log(key);

}

// 输出:

// ‘name’

// ‘age’

// ‘sharedProperty’

“`

这就不是我们想要的结果了。在实际开发中,你可能无意间引入了一个库,它修改了 Object.prototype,然后你的 for...in 循环就开始出现意想不到的行为。

为了避免这个问题,通常需要加上 hasOwnProperty() 来检查这个属性是不是对象自身的,而不是从原型链上继承来的。

javascript

for (let key in person) {

if (person.hasOwnProperty(key)) {

console.log(key);

}

}

// 输出:

// 'name'

// 'age'

这样就安全多了。

绝对不要用 for...in 遍历数组

很多人刚开始学的时候,会觉得既然 for...in 能遍历对象,那数组也是对象,应该也行吧? 理论上可以,但千万别这么做。

原因有几个:

1. 它遍历的是索引,而且是字符串类型。 你拿到的 index 是 “0”, “1”, “2” 这样的字符串,而不是数字 0, 1, 2。如果你直接拿去做数学运算,可能会得到奇怪的结果。

2. 它不能保证顺序。 虽然大多数现代浏览器会按顺序遍历,但规范本身并没有保证这一点。对于数组来说,顺序极其重要。

3. 它会遍历到数组的非数字属性和原型链上的属性。 这和上面提到的对象问题一样,甚至更糟。数组也可能被添加自定义属性。

“`javascript

Array.prototype.customMethod = function() {};

const arr = [‘a’, ‘b’, ‘c’];

arr.customProperty = ‘这是一个自定义属性’;

for (let i in arr) {

console.log(i);

}

// 可能的输出 (顺序不保证):

// ‘0’

// ‘1’

// ‘2’

// ‘customProperty’

// ‘customMethod’

“`

看到没?连原型上的方法都出来了,这绝对是灾难。所以,记住一句话:for...in 是为普通对象准备的,不是为数组准备的。

再来看 for...of,现代 JavaScript 遍历的救星

for...of 是在 ES6 中引入的,它的出现就是为了解决 for...in 的那些问题,并提供一个统一的遍历接口。

它的核心是迭代器协议(Iterator Protocol)。 只要一个数据结构实现了这个协议,它就是“可迭代的”(iterable),也就可以用 for...of 来遍历。

常见的可迭代对象包括:

数组 (Array)

字符串 (String)

Map

Set

NodeList (浏览器环境中的 DOM 集合)

for...of 的语法非常简洁,而且它直接遍历的是

我们用 for...of 来遍历一个数组:

“`javascript

const arr = [‘a’, ‘b’, ‘c’];

for (let value of arr) {

console.log(value);

}

// 输出:

// ‘a’

// ‘b’

// ‘c’

“`

干净利落。没有多余的属性,没有索引类型的问题,顺序也是正确的。

遍历字符串也一样方便:

“`javascript

const str = “hello”;

for (let char of str) {

console.log(char);

}

// 输出:

// ‘h’

// ‘e’

// ‘l’

// ‘l’

// ‘o’

“`

但是,for...of 不能直接用在普通对象上

这是新手最容易犯的错。如果你尝试用 for...of 遍历一个普通对象,会直接报错。

“`javascript

const person = {

name: ‘老王’,

age: 30

};

for (let value of person) { // 这行会报错

console.log(value);

}

// Uncaught TypeError: person is not iterable

“`

原因很简单:普通对象默认没有实现迭代器协议。 for...of 不知道该如何从这个对象里一个一个地取值。

那如果你真的想用 for...of 的简洁语法来遍历对象呢?也不是不行,需要借助一些辅助方法,把对象转换成可迭代的结构。常用的有三个:

  1. Object.keys(): 获取对象的键组成的数组。

    javascript

    for (let key of Object.keys(person)) {

    console.log(key + ': ' + person[key]);

    }

  2. Object.values(): 获取对象的值组成的数组。

    javascript

    for (let value of Object.values(person)) {

    console.log(value);

    }

  3. Object.entries(): 获取对象的键值对组成的数组,每个键值对是一个 [key, value] 形式的小数组。

    javascript

    for (let [key, value] of Object.entries(person)) {

    console.log(key + ': ' + value);

    }

我个人最推荐 Object.entries(),因为它同时提供了键和值,而且通过解构赋值 [key, value],代码非常清晰易读。

场景选择:什么时候用哪个?

现在逻辑就很清晰了。

  • 当你需要遍历一个普通对象的属性时,使用 for...in。并且,为了保险起见,最好总是带上 hasOwnProperty() 的检查。
  • 当你需要遍历数组、字符串、Map、Set 等可迭代数据结构的值时,用 for...of。这是最安全、最直接的方式。
  • 如果你想用 for...of 的方式来遍历普通对象,请先用 Object.keys()Object.values()Object.entries() 把它转换成一个数组。

for和of的区别

本站部分图片和内容来自网友上传和分享,版权归原作者所有,如有侵权,请联系删除!若转载,请注明出处:https://www.rzedutec.com/p/63332/

(0)
于老师于老师
上一篇 2025年10月24日
下一篇 2025年10月24日

相关推荐

发表回复

登录后才能评论