在 For Of 循环中使用对象

IT技术 javascript for-loop ecmascript-6 iterable
2021-03-01 12:51:19

为什么不能在 for of 循环中使用对象?或者这是浏览器的错误?此代码在 Chrome 42 中不起作用,表示 undefined 不是函数:

test = { first: "one"}

for(var item of test) {
  console.log(item)
}
6个回答

for..of环路仅支持像数组可迭代的对象,而不是对象。

要迭代对象的值,请使用:

for (var key in test) {
    var item = test[key];
}
@DanielHerr 如果对象“基类”是可迭代的,那么任何函数/日期/等“子类”以及其他并发症也是如此。不过,请参阅esdiscuss.org/topic/es6-iteration-over-object-values#content-5以获得对您的问题的更彻底/准确的讨论。
2021-04-20 12:51:19
使用此 for..in 解决方案,您在技术上还需要检查if (test.hasOwnProperty(key)){ ... }吗?或者那是不需要的?
2021-04-30 12:51:19
@DanielHerr 有一个.iterable成员函数,这是当您尝试在对象(没有它)上使用它时出现错误的地方。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
2021-05-09 12:51:19
我的意思是,为什么对象没有那个?本地添加它会有什么问题?
2021-05-13 12:51:19
@DanielHerr 我没有答案,你得问问设计语言的人。
2021-05-16 12:51:19

您可以使用以下语法:

const myObject = {
  first: "one",
  second: "two",
};

for (const [key, value] of Object.entries(myObject)) {
  console.log(key, value);  // first one, second two
}

然而, Object.entries 现在支持很差 在 IE 中不起作用 或 iOS Safari. 你会大概可能需要一个 polyfill。有关最新消息,请参阅https://caniuse.com/mdn-javascript_builtins_object_entries

另请参阅Object.keys仅迭代键或Object.values迭代值。

如果您将数据存储在键值存储中,请使用Map专为此目的而设计的。

如果你必须使用一个对象,ES2017 (ES8) 允许你使用Object.values

const foo = { a: 'foo', z: 'bar', m: 'baz' };
for (let value of Object.values(foo)) {
    console.log(value);
}

如果还不支持,请使用 polyfill: Alternative version forObject.values()

最后,如果您支持不支持此语法的旧环境,则必须求助于使用forEachand Object.keys

var obj = { a: 'foo', z: 'bar', m: 'baz' };
Object.keys(obj).forEach(function (prop) {
    var value = obj[prop];
    console.log(value);
});
使用这些复杂的示例比使用简单的有什么优势for-in吗?
2021-04-18 12:51:19
不能扩展对象原型来支持这个吗?
2021-04-24 12:51:19
为什么使用地图而不是对象?
2021-05-04 12:51:19
Object.entries 可以在不接触原型的情况下通过 polyfill。
2021-05-10 12:51:19
@SonicSoul:技术上是的,但通常不建议扩展 Object 原型,因为(几乎)所有东西都继承自它。
2021-05-12 12:51:19

ECMAScript 2015/ES6 中的迭代器、可迭代和 for..of 循环

let tempArray = [1,2,3,4,5];

for(element of tempArray) {
  console.log(element);
}

// 1
// 2
// 3
// 4
// 5

但是如果我们这样做

let tempObj = {a:1, b:2, c:3};

for(element of tempObj) {
   console.log(element);
}
// error

我们得到错误,因为for..of循环仅适用于Iterables,即具有遵守Iterator 协议@@iterator的对象,这意味着它必须具有一个带有next方法的对象next 方法没有参数,它应该返回一个具有这两个属性的对象。

done : 当为真时表示序列已经结束,假意味着可能有更多的值 value:这是序列中的当前项目

因此,要使对象Iterable使其与for..of 一起工作,我们可以:

1 . 通过Symbol.iterator属性分配给它神秘的@@iterator属性,使一个对象成为一个Iterable这里是如何:

let tempObj = {a:1, b:2, c:3};

tempObj[Symbol.iterator]= () => ({
next: function next () {
return {
    done: Object.keys(this).length === 0,
    value: Object.keys(this).shift()
     }
    }
  })

for(key in tempObj){
 console.log(key)
}
// a
// b
// c

2.使用Object.entries,它返回一个Iterable

let tempObj = {a:1, b:2, c:3};

for(let [key, value] of Object.entries(tempObj)) {
    console.log(key, value);
}
// a 1
// b 2
// c 3

3.使用Object.keys,方法如下:

let tempObj = {a:1, b:2, c:3};
for (let key of Object.keys(tempObj)) {
    console.log(key);
}

// a
// b
// c

希望这可以帮助!!!!!!

我使用以下代码使对象可迭代:

Object.prototype[Symbol.iterator] = function*() {
 for(let key of Object.keys(this)) {
  yield([ key, this[key] ])
} }

用法:

for(let [ key, value ] of {}) { }

或者:

for(let [ key, value ] of Object.entries({})) { }
@ user1703761 这是公认的解决方案,因为它有效。请解释如果它如此可怕会导致什么问题。
2021-04-18 12:51:19
有各种各样的问题,主要是向前兼容的问题。一个例子是之前命名为 contains 的 Array.prototype.includes 但 Moo Tools 扩展了原型并且实现不兼容,参见bugzilla.mozilla.org/show_bug.cgi?id=1075059 也可以查找原型库 desaster ;)
2021-04-22 12:51:19
我相信这不会有前向兼容性问题,因为如果将迭代器添加到对象中,这将覆盖它,如果将迭代器添加到对象子类型中,它将使用子类型迭代器。
2021-04-27 12:51:19
不知道为什么这是公认的解决方案。除非它是一个 polyfill,否则修改原型总是一个糟糕的主意。
2021-05-03 12:51:19
嘿伙计们,修改原型是个坏主意!!!让我们为 OP 实际回答这个问题而感到羞耻!
2021-05-15 12:51:19