在 For Of 循环中使用对象
Posted
技术标签:
【中文标题】在 For Of 循环中使用对象【英文标题】:Using Objects in For Of Loops 【发布时间】:2015-07-05 06:50:30 【问题描述】:为什么不能在 for of 循环中使用对象?或者这是一个浏览器错误?这段代码在 Chrome 42 中不起作用,说 undefined is not a function:
test = first: "one"
for(var item of test)
console.log(item)
【问题讨论】:
测试是数组还是对象? @KickButtowski,你没看到吗?它绝对是一个对象。 for (let key of Object.keys(test)) ... 【参考方案1】:for..of loop 仅支持数组等可迭代对象,不支持对象。
要遍历对象的值,请使用:
for (var key in test)
var item = test[key];
【讨论】:
@DanielHerr 有一个.iterable
成员函数,当您尝试在一个对象(没有它)上使用它时,就会出现错误。 developer.mozilla.org/en-US/docs/Web/javascript/Reference/…
我的意思是,为什么对象没有那个?原生添加会有什么问题?
@DanielHerr 我没有答案,你得问问设计语言的人。
@DanielHerr 如果对象“基类”是可迭代的,那么任何函数/日期/等“子类”以及其他复杂性也将是可迭代的。不过,请参阅 esdiscuss.org/topic/es6-iteration-over-object-values#content-5 以更彻底/准确地讨论您的问题。
有了这个 for..in 解决方案,从技术上讲,您是否还需要检查if (test.hasOwnProperty(key)) ...
?还是不需要?【参考方案2】:
您可以使用以下语法:
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
仅迭代值。
【讨论】:
【参考方案3】:如果您将数据存储在键值存储中,please use 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 for Object.values()
最后,如果您支持不支持此语法的旧环境,您将不得不使用forEach
和Object.keys
:
var obj = a: 'foo', z: 'bar', m: 'baz' ;
Object.keys(obj).forEach(function (prop)
var value = obj[prop];
console.log(value);
);
【讨论】:
不能扩展对象原型来支持这个吗? @SonicSoul:技术上是的,但通常不建议扩展 Object 原型,因为(几乎)所有东西都继承自它。Object.entries
可以在不接触原型的情况下进行填充。
为什么使用地图而不是对象?
使用这些复杂的例子比简单的for-in
有什么好处吗?【参考方案4】:
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 方法的对象。下一个方法不带参数,它应该返回一个具有这两个属性的对象。
done:当为真时表示序列已经结束,假表示可能有更多的值 值:这是序列中的当前项
因此,要使对象 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
希望对你有帮助!!!!!!
【讨论】:
【参考方案5】:我用这段代码使对象可迭代:
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())
【讨论】:
不知道为什么这是公认的解决方案。除非它是 polyfill,否则修改原型总是一个糟糕的主意。 @user1703761 这是公认的解决方案,因为它有效。请解释如果它如此可怕会导致什么问题。 有各种各样的问题,主要是前向兼容性问题。一个例子是 Array.prototype.includes 之前的名字 contains 但 Moo Tools 扩展了原型并且实现不兼容,请参阅 bugzilla.mozilla.org/show_bug.cgi?id=1075059 也查找原型库 desaster ;) 我相信这不会有前向兼容性问题,因为如果将迭代器添加到对象,这将覆盖它,如果将迭代器添加到对象子类型,它将使用子类型迭代器。 大家好,修改原型是个坏主意!!!让我们为实际给出问题的答案而感到羞耻!【参考方案6】:因为对象字面量没有Symbol.iterator 属性。具体来说,你只能用for...of循环遍历String、Array、Map、Set、arguments、NodeList(不广泛支持)和Generator。
要处理 Object Literal 迭代,您有两种选择。
为...在
for(let key in obj)
console.log(obj[key]);
Object.keys + forEach
Object.keys(obj).forEach(function(key)
console.log(obj[key]);
);
【讨论】:
【参考方案7】:答案是否定的。不可能将 For..Of 与 Object 字面量一起使用。
我同意 Overv 的观点,即 For..Of 仅适用于可迭代对象。 我有完全相同的问题,因为我使用对象通过 for..in 迭代键和值。但我刚刚意识到这就是 ES6 MAPS 和 SETS 的用途。
let test = new Map();
test.set('first', "one");
test.set('second', "two");
for(var item of test)
console.log(item); // "one" "two"
因此它实现了不必使用 for..In(通过 hasOwnProperty 验证)和不必使用 Object.keys() 的目标。
此外,您的键不限于字符串。您可以使用数字、对象或其他文字。
【讨论】:
【参考方案8】:对象字面量没有内置的迭代器,这是使用for...of
循环所必需的。但是,如果您不想麻烦地将自己的[Symbol.iterator]
添加到您的对象中,您可以简单地使用Object.keys()
方法。此方法返回一个 Array
对象,该对象已经具有内置迭代器,因此您可以将其与 for...of
循环一起使用,如下所示:
const myObject =
country: "Canada",
province: "Quebec",
city: "Montreal"
for (let i of Object.keys(myObject))
console.log("Key:", i, "| Value:", myObject[i]);
//Key: country | Value: Canada
//Key: province | Value: Quebec
//Key: city | Value: Montreal
【讨论】:
每次都使用key比添加一次迭代器更麻烦。此外,Object.keys() 是 ES5。【参考方案9】:可以在任何给定对象上定义迭代器,这样您就可以为每个对象放置不同的逻辑
var x = a: 1, b: 2, c: 3
x[Symbol.iterator] = function* ()
yield 1;
yield 'foo';
yield 'last'
那就直接迭代x
for (let i in x)
console.log(i);
//1
//foo
//last
可以在Object.prototype
对象上做同样的事情,并为所有对象提供一个通用迭代器
Object.prototype[Symbol.iterator] = function*()
for(let key of Object.keys(this))
yield key
然后像这样迭代你的对象
var t = a :'foo', b : 'bar'
for(let i of t)
console.log(t[i]);
或者这样
var it = t[Symbol.iterator](), p;
while(p = it.next().value)
console.log(t[p])
【讨论】:
【参考方案10】:我只是做了以下事情来轻松解决我的问题。
for (let key in obj)
if(obj.hasOwnProperty(key)
console.log(`$key: $obj[key]`);
【讨论】:
【参考方案11】:使用Object.keys 来获取键数组怎么样?然后forEach on the Array?
obj = a: 1, b:2
Object.keys(obj).forEach( key => console.log(`$key => $obj[key]`))
【讨论】:
【参考方案12】:如何使用
function* entries(obj)
for (let key of Object.keys(obj))
yield [key, obj[key]];
for ([key, value] of entries(a: "1", b: "2"))
console.log(key + " " + value);
【讨论】:
【参考方案13】:在 ES6 中你可以使用生成器:
var obj = 1: 'a', 2: 'b';
function* entries(obj)
for (let key of Object.keys(obj))
yield [key, obj[key]];
let generator = entries(obj);
let step1 = generator.next();
let step2 = generator.next();
let step3 = generator.next();
console.log(JSON.stringify(step1)); // "value":["1","a"],"done":false
console.log(JSON.stringify(step2)); // "value":["2","b"],"done":false
console.log(JSON.stringify(step3)); // "done":true
Here is the jsfiddle.
在输出中,您将获得一个带有 "value"
和 "done"
键的对象。 "Value"
包含您想要它拥有的所有内容,"done"
是布尔迭代的当前状态。
【讨论】:
【参考方案14】:使用 Array Destruction 您可以使用 forEach
进行如下迭代
const obj = a: 5, b: 7, c: 9 ;
Object.entries(obj).forEach(([key, value]) =>
console.log(`$key $value`); // "a 5", "b 7", "c 9"
);
【讨论】:
以上是关于在 For Of 循环中使用对象的主要内容,如果未能解决你的问题,请参考以下文章