我有一个 JavaScript 对象,如下所示:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
如何循环遍历 p
的所有元素(p1
、p2
、p3
...)并获取它们的键和值?
您可以使用其他人所示的 for-in
循环。但是,您还必须确保您获得的密钥是对象的实际属性,而不是来自原型。
这是片段:
var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (var key in p) { if (p.hasOwnProperty(key)) { console.log(key + " -> " + p[key]); } }
使用 Object.keys() 替代方案:
var p = { 0: "value1", "b": "value2", key: "value3" }; for (var key of Object.keys(p)) { console.log(key + " -> " + p[key]) }
注意使用 for-of
而不是 for-in
,如果不使用它将在命名属性上返回 undefined,并且 Object.keys()
确保仅使用对象自己的属性而不使用整个原型链属性
使用新的 Object.entries()
方法:
注意:Internet Explorer 本身不支持此方法。您可以考虑为旧版浏览器使用 Polyfill。
const p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
for (let [key, value] of Object.entries(p)) {
console.log(`${key}: ${value}`);
}
在 ECMAScript 5 下,您可以组合 Object.keys()
和 Array.prototype.forEach()
:
var obj = { first: "John", last: "Doe" };
Object.keys(obj).forEach(function(key) {
console.log(key, obj[key]);
});
ECMAScript 6 添加了 for...of
:
for (const key of Object.keys(obj)) {
console.log(key, obj[key]);
}
ECMAScript 8 添加了 Object.entries()
以避免在原始对象中查找每个值:
Object.entries(obj).forEach(
([key, value]) => console.log(key, value)
);
您可以组合 for...of
、解构和 Object.entries
:
for (const [key, value] of Object.entries(obj)) {
console.log(key, value);
}
Object.keys()
和 Object.entries()
都以与 for...in
循环相同的顺序迭代属性但忽略原型链。只有对象自己的可枚举属性被迭代。
Object.forEach(obj, function (value, key) {...})
? :( 当然 obj.forEach(function...)
会更短并且是 Array.prototype.forEach
的补充,但这会冒着让对象定义自己的 forEach
属性的风险。我想 Object.keys
可以防止回调修改对象的键。
您必须使用 for-in 循环
但是在使用这种循环时要非常小心,因为这会循环原型链上的所有属性。
因此,在使用 for-in 循环时,始终使用 hasOwnProperty
方法来确定迭代中的当前属性是否真的是您正在检查的对象的属性:
for (var prop in p) {
if (!p.hasOwnProperty(prop)) {
//The current property is not a direct property of p
continue;
}
//Do your logic with the property here
}
{ }
,因为没有它们的 if
会让人有点不清楚什么是 if
的一部分,什么不是。但我想这只是一个意见问题:)
{ }
,主要是为了避免以后需要在 if
范围内添加某些内容时造成混淆。
如果我们不提到循环对象的替代方法,这个问题就不会完整。
如今,许多著名的 JavaScript 库都提供了自己的方法来迭代集合,即遍历数组、对象和类数组对象。这些方法使用方便,完全兼容任何浏览器。
如果你使用 jQuery,你可以使用 jQuery.each() 方法。它可用于无缝迭代对象和数组: $.each(obj, function(key, value) { console.log(key, value); });在 Underscore.js 中,您可以找到方法 _.each(),它遍历元素列表,将每个元素依次生成给提供的函数(注意 iteratee 函数中参数的顺序!):_.each(obj,函数(值,键){ console.log(键,值);}); Lo-Dash 提供了几种迭代对象属性的方法。基本的 _.forEach()(或者它的别名 _.each())对于循环遍历对象和数组很有用,但是(!)具有长度属性的对象被视为数组,为了避免这种行为,建议使用 _ .forIn() 和 _.forOwn() 方法(这些也有值参数首先出现): _.forIn(obj, function(value, key) { console.log(key, value); }); _.forIn() 迭代对象自己的和继承的可枚举属性,而 _.forOwn() 仅迭代对象自己的属性(基本上检查 hasOwnProperty 函数)。对于简单的对象和对象字面量,这些方法中的任何一个都可以正常工作。
通常,所有描述的方法与任何提供的对象具有相同的行为。除了使用原生 for..in
循环通常比任何抽象(例如 jQuery.each()
)更快,这些方法更容易使用,需要更少的编码并提供更好的错误处理。
前言:
对象属性可以是自己的(属性在对象本身上)或继承(不在对象本身上,在其原型之一上)。
对象属性可以是可枚举的或不可枚举的。不可枚举的属性被排除在许多属性枚举/数组之外。
属性名称可以是字符串或符号。名称为符号的属性被排除在许多属性枚举/数组之外。
在 2018 年,您可以选择循环遍历对象的属性(列表后面有一些示例):
for-in [MDN, spec] — 一种循环结构,循环遍历对象的可枚举属性的名称,包括继承的属性,其名称为字符串 Object.keys [MDN, spec] — 提供对象名称数组的函数对象自己的、名称为字符串的可枚举属性。 Object.values [MDN, spec] — 一个函数,提供对象自身的可枚举属性的值数组。 Object.entries [MDN, spec] — 一个函数,提供对象自身的可枚举属性的名称和值的数组(数组中的每个条目都是一个 [name, value] 数组)。 Object.getOwnPropertyNames [MDN, spec] — 一个函数,提供名称为字符串的对象自身属性(甚至是不可枚举属性)的名称数组。 Object.getOwnPropertySymbols [MDN, spec] — 一个函数,提供名称为符号的对象自身属性(甚至是不可枚举的属性)的名称数组。 Reflect.ownKeys [MDN, spec] — 提供对象自身属性(甚至是不可枚举属性)名称数组的函数,无论这些名称是字符串还是符号。如果您想要一个对象的所有属性,包括不可枚举的继承属性,您需要使用循环和 Object.getPrototypeOf [MDN, spec] 并在每个对象上使用 Object.getOwnPropertyNames、Object.getOwnPropertySymbols 或 Reflect.ownKeys原型链(此答案底部的示例)。
对于除 for-in
之外的所有这些,您将在数组上使用某种循环构造(for
、for-of
、forEach
等)。
例子:
for-in
:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 o.question = "Life, the Universe, and Everything"; // 以交易品种命名的属性 o[Symbol("author")] = "Douglas Adams"; for (const name in o) { const value = o[name]; console.log(`${name} = ${value}`); }
Object.keys
(带有 for-of
循环,但您可以使用任何循环结构):
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 o.question = "Life, the Universe, and Everything"; // 以交易品种命名的属性 o[Symbol("author")] = "Douglas Adams"; for (const name of Object.keys(o)) { const value = o[name]; console.log(`${name} = ${value}`); }
Object.values
:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 o.question = "Life, the Universe, and Everything"; // 以交易品种命名的属性 o[Symbol("author")] = "Douglas Adams"; for (Object.values(o) 的常量值) { console.log(`${value}`); }
Object.entries
:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 o.question = "Life, the Universe, and Everything"; // 以交易品种命名的属性 o[Symbol("author")] = "Douglas Adams"; for (const [name, value] of Object.entries(o)) { console.log(`${name} = ${value}`); }
Object.getOwnPropertyNames
:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 o.question = "Life, the Universe, and Everything"; // 以交易品种命名的属性 o[Symbol("author")] = "Douglas Adams"; for (Object.getOwnPropertyNames(o) 的常量名称) { 常量值 = o[name]; console.log(`${name} = ${value}`); }
Object.getOwnPropertySymbols
:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 o.question = "Life, the Universe, and Everything"; // 以交易品种命名的属性 o[Symbol("author")] = "Douglas Adams"; for (Object.getOwnPropertySymbols(o) 的常量名称) { 常量值 = o[名称]; console.log(`${String(name)} = ${value}`); }
Reflect.ownKeys
:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 o.question = "Life, the Universe, and Everything"; // 以交易品种命名的属性 o[Symbol("author")] = "Douglas Adams"; for (Reflect.ownKeys(o) 的常量名称) { 常量值 = o[name]; console.log(`${String(name)} = ${value}`); }
所有属性,包括继承的不可枚举属性:
// 要继承的原型对象,具有字符串命名的属性 const p = {answer: 42}; // 我们要查看的对象,它继承自 `p` const o = Object.create(p); // 一个字符串命名的属性 o.question = "Life, the Universe, and Everything"; // 以交易品种命名的属性 o[Symbol("author")] = "Douglas Adams"; for (let depth = 0, current = o; current; ++depth, current = Object.getPrototypeOf(current)) { for (const name of Reflect.ownKeys(current)) { const value = o[name]; console.log(`[${depth}] ${String(name)} = ${String(value)}`); } } .as-console-wrapper { max-height: 100% !important; }
你可以像这样迭代它:
for (var key in p) {
alert(p[key]);
}
请注意,key
不会采用属性的值,它只是一个索引值。
在 ECMAScript 5 中,您在文字的迭代字段中有新方法 - Object.keys
您可以在 MDN 上查看更多信息
我的选择是在当前版本的浏览器(Chrome30、IE10、FF25)中作为更快的解决方案
var keys = Object.keys(p),
len = keys.length,
i = 0,
prop,
value;
while (i < len) {
prop = keys[i];
value = p[prop];
i += 1;
}
您可以将此方法的性能与 jsperf.com 上的不同实现进行比较:
扩展实现
对象键迭代
对象字面量迭代
您可以在 Kangax's compat table 上看到浏览器支持
对于旧浏览器,您有 simple 和 full polyfill
升级版:
perfjs.info
上此问题中所有最流行案例的性能比较:
表现
今天 2020.03.06 我在 MacOs High Sierra v10.13.6 上的 Chrome v80.0、Safari v13.0.5 和 Firefox 73.0.1 上执行所选解决方案的测试
结论
对于大小对象的所有浏览器,基于 for-in (A,B) 的解决方案都很快(或最快)
令人惊讶的 for-of (H) 解决方案在 chrome 上对于大小物体来说速度很快
基于显式索引 i (J,K) 的解决方案在小对象的所有浏览器上都非常快(对于大对象来说,Firefox 也很快,但在其他浏览器上速度中等)
基于迭代器 (D,E) 的解决方案最慢,不推荐
解决方案 C 对于大物体来说是慢的,对于小物体来说是中慢的
https://i.stack.imgur.com/M6NzO.png
细节
进行了性能测试
小对象 - 有 3 个字段 - 您可以在您的机器上执行测试这里
'大' 对象 - 有 1000 个字段 - 你可以在你的机器上执行测试 这里
下面的片段介绍了使用的解决方案
function A(obj,s='') { for (let key in obj) if (obj.hasOwnProperty(key)) s+=key+'->'+obj[key] + ' ';返回 s; } function B(obj,s='') { for (let key in obj) s+=key+'->'+obj[key] + ' ';返回 s; } 函数 C(obj,s='') { const map = new Map(Object.entries(obj)); for (let [key,value] of map) s+=key+'->'+value + ' ';返回 s; } function D(obj,s='') { let o = { ...obj, *[Symbol.iterator]() { for (const i of Object.keys(this)) yield [i, this[i] ]; } } for (let [key,value] of o) s+=key+'->'+value + ' ';返回 s; } function E(obj,s='') { let o = { ...obj, *[Symbol.iterator]() {yield *Object.keys(this)} } for (let key of o) s+=key+ '->'+o[键] + '';返回 s; } function F(obj,s='') { for (let key of Object.keys(obj)) s+=key+'->'+obj[key]+' ';返回 s; } function G(obj,s='') { for (let [key, value] of Object.entries(obj)) s+=key+'->'+value+' ';返回 s; } function H(obj,s='') { for (let key of Object.getOwnPropertyNames(obj)) s+=key+'->'+obj[key]+' ';返回 s; } function I(obj,s='') { for (Reflect.ownKeys(obj)的const key) s+=key+'->'+obj[key]+'';返回 s; } 函数 J(obj,s='') { 让键 = Object.keys(obj); for(let i = 0; i < keys.length; i++){ let key = keys[i]; s+=key+'->'+obj[key]+''; } 返回 s; } 函数 K(obj,s='') { var keys = Object.keys(obj), len = keys.length, i = 0; while (i < len) { 让键 = 键 [i]; s+=key+'->'+obj[key]+'';我 += 1; } 返回 s; } function L(obj,s='') { Object.keys(obj).forEach(key=> s+=key+'->'+obj[key]+' ' );返回 s; } function M(obj,s='') { Object.entries(obj).forEach(([key, value]) => s+=key+'->'+value+' ');返回 s; } function N(obj,s='') { Object.getOwnPropertyNames(obj).forEach(key => s+=key+'->'+obj[key]+' ');返回 s; } 函数 O(obj,s='') { Reflect.ownKeys(obj).forEach(key=> s+=key+'->'+obj[key]+' ' );返回 s; } // 测试 var p = { "p1": "value1", "p2": "value2", "p3": "value3" };让 log = (name,f) => console.log(`${name} ${f(p)}`) log('A',A);日志('B',B);日志('C',C);日志('D',D);日志('E',E);日志('F',F);日志('G',G);日志('H',H);日志('我',我);日志('J',J);日志('K',K);日志('L',L);日志('M',M);日志('N',N);日志('O',O);此代码段仅提供选定的解决方案
这是 chrome 上小物体的结果
https://i.stack.imgur.com/z8KJL.png
for(key in p) {
alert( p[key] );
}
注意:您可以对数组执行此操作,但您也将遍历 length
和其他属性。
key
将只采用索引值,因此只会提醒 0、1、2 等...您需要访问 p[key]。
var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }
在警报中弹出“p1”和“p2”,那有什么问题???
由于 es2015 越来越受欢迎,我发布了这个答案,其中包括使用生成器和迭代器来平滑地遍历 [key, value]
对。就像在其他语言中一样,例如 Ruby。
好的,这是一个代码:
const MyObject = { 'a': 'Hello', 'b': 'it\'s', 'c': 'me', 'd': 'you', 'e': '正在寻找', 'f' : 'for', [Symbol.iterator]: function*() { for (const i of Object.keys(this)) { yield [i, this[i]]; } } }; for (const [k, v] of MyObject) { console.log(`这里是键 ${k},这里是值 ${v}`); }
有关如何创建迭代器和生成器的所有信息,您可以在开发人员 Mozilla 页面上找到。
希望它对某人有所帮助。
编辑:
ES2017 将包含 Object.entries
,这将使迭代对象中的 [key, value]
对更加容易。根据ts39阶段信息,现在已知它将成为标准的一部分。
我认为是时候更新我的答案,让它变得比现在更新鲜。
const MyObject = { 'a': 'Hello', 'b': 'it\'s', 'c': 'me', 'd': 'you', 'e': '正在寻找', 'f' : '为了', }; for (const [k, v] of Object.entries(MyObject)) { console.log(`这里是键 ${k},这里是值 ${v}`); }
您可以在 MDN 页面上找到有关使用情况的更多信息
在查看了这里的所有答案后,我自己的使用不需要 hasOwnProperty,因为我的 json 对象是干净的;添加任何额外的javascript处理真的没有意义。这就是我正在使用的所有内容:
for (var key in p) {
console.log(key + ' => ' + p[key]);
// key is key
// value is p[key]
}
Object.prototype
上设置了一个属性,那么它将被 for..in
枚举。如果您确定没有使用任何执行此操作的库,则无需调用 hasOwnProperty
。
Object.create(null)
创建它可以完全干净
通过带有 forEach() 的原型,它应该跳过原型链属性:
Object.prototype.each = function(f) {
var obj = this
Object.keys(obj).forEach( function(key) {
f( key , obj[key] )
});
}
//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3
obj = { print: 1, each: 2, word: 3 }
产生 TypeError: number is not a function
。使用 forEach
匹配类似的 Array
函数可能会在一定程度上降低风险。
单行和更具可读性的代码可以是..
Object.entries(myObject).map(([key, value]) => console.log(key, value))
有趣的是,这些答案中的人都触及了 Object.keys()
和 for...of
但从未将它们结合起来:
var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
console.log(key + ':' + map[key]);
您不能只是 for...of
一个 Object
,因为它不是一个迭代器,并且 for...index
或 .forEach()
使用 Object.keys()
是丑陋的/低效的。
我很高兴大多数人都在避免来自for...in
(有或没有检查.hasOwnProperty()
),因为这也有点乱,所以除了我上面的答案之外,我在这里说......
你可以让普通的对象关联迭代!行为就像 Map
直接使用在 Chrome 和 FF 中工作的花哨的 for...of
DEMO(我假设仅 ES6)
var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
//key:value
console.log(pair[0] + ':' + pair[1]);
//or
for (let [key, value] of ordinaryObject)
console.log(key + ':' + value);
只要你在下面包括我的垫片:
//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
var keys = Object.keys(this)[Symbol.iterator]();
var obj = this;
var output;
return {next:function() {
if (!(output = keys.next()).done)
output.value = [output.value, obj[output.value]];
return output;
}};
};
无需创建一个没有漂亮语法糖的真实 Map 对象。
var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
console.log(pair[0] + ':' + pair[1]);
事实上,有了这个 shim,如果你仍然想利用 Map 的其他功能(而不是全部填充)但仍然想使用整洁的对象表示法,因为对象现在是可迭代的,你现在可以用它制作一个 Map!
//shown in demo
var realMap = new Map({well:'hello', there:'!'});
对于那些一般不喜欢 shim 或与 prototype
混淆的人,请随意在 window 上创建该函数,然后将其称为 getObjIterator()
;
//no prototype manipulation
function getObjIterator(obj) {
//create a dummy object instead of adding functionality to all objects
var iterator = new Object();
//give it what the shim does but as its own local property
iterator[Symbol.iterator] = function() {
var keys = Object.keys(obj)[Symbol.iterator]();
var output;
return {next:function() {
if (!(output = keys.next()).done)
output.value = [output.value, obj[output.value]];
return output;
}};
};
return iterator;
}
现在您可以将其作为普通函数调用,不影响其他任何内容
var realMap = new Map(getObjIterator({well:'hello', there:'!'}))
或者
for (let pair of getObjIterator(ordinaryObject))
There's no reason why that wouldn't work.
欢迎来到未来。
For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then;
ordinaryObject
这样的变量名称,以强调魔法仍然适用于这些类型)。你检查过演示吗?什么不适合你,@noɥʇʎԀʎzɐɹƆ? (PS 你的 SE 头像是老板)
您还可以使用 Object.keys() 并遍历对象键,如下所示:
var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; Object.keys(p).forEach((key)=> { console.log(key +' -> '+ p[key]); });
在 Object.keys()
上使用 for-of
喜欢:
让对象= {“key1”:“value1”,“key2”:“value2”,“key3”:“value3”}; for (let key of Object.keys(object)) { console.log(key + " : " + object[key]) }
var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (var key in p) { if (p.hasOwnProperty(key)) { console.log(key + " = " + p[key]); } }
输出:
p1 = values1
p2 = values2
p3 = values3
Object.keys(obj) :数组检索所有可枚举自己(非继承)属性的所有字符串值键。
因此,通过使用 hasOwnProperty 测试每个对象键,它提供了与您想要的相同的键列表。您不需要额外的测试操作,并且 Object.keys( obj ).forEach(function( key ){})
应该更快。让我们证明一下:
var uniqid = function(){ var text = "", i = 0, possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; for( ; i < 32; i++ ) { text += possible.charAt( Math.floor( Math.random() * possible.length ) ); } 返回文本; },CYCLES = 100000,obj = {},p1,p2,p3,键; // 使用随机属性填充对象 Array.apply( null, Array( CYCLES ) ).forEach(function(){ obj[ uniqid() ] = new Date() }); // 方法#1 p1 = performance.now(); Object.keys( obj ).forEach(function( key ){ var waste = obj[ key ]; }); p2 = 性能.now(); console.log("Object.keys 方法花费了 " + (p2 - p1) + " 毫秒。"); // 方法 #2 for( key in obj ) { if ( obj.hasOwnProperty( key ) ) { var waste = obj[ key ]; } } p3 = performance.now(); console.log("for...in/hasOwnProperty 方法花费了 " + (p3 - p2) + " 毫秒。");
在我的 Firefox 中,我有以下结果
Object.keys 方法耗时 40.21101451665163 毫秒。
for...in/hasOwnProperty 方法花费了 98.26163508463651 毫秒。
PS。在 Chrome 上差异更大http://codepen.io/dsheiko/pen/JdrqXa
PS2:在 ES6(EcmaScript 2015)中,您可以更好地迭代可迭代对象:
让 map = new Map().set('a', 1).set('b', 2); for (let pair of map) { console.log(pair); } // 或者让 map = new Map([ [false, 'no'], [true, 'yes'], ]); map.forEach((value, key) => { console.log(key, value); });
of
without creating Map
s
在最新的 ES 脚本中,您可以执行以下操作:
让 p = {foo: "bar"}; for (let [key, value] of Object.entries(p)) { console.log(key, value); }
只有没有依赖关系的 JavaScript 代码:
var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
keys = Object.keys(p); // ["p1", "p2", "p3"]
for(i = 0; i < keys.length; i++){
console.log(keys[i] + "=" + p[keys[i]]); // p1=value1, p2=value2, p3=value3
}
Object.keys()
方法返回给定对象自己的可枚举属性的数组。详细了解它here
var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; Object.keys(p).map((key)=> console.log(key + "->" + p[key]))
这是另一种遍历对象的方法。
var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; Object.keys(p).forEach(key => { console.log(key, p[key]) })
for
方法可能更高效。
在javascript中迭代对象的多种方法
使用 for...in 循环
var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (let key in p){ if(p.hasOwnProperty(key)){ console.log(`${key} : ${p[key]}`) } }
使用 for...of 循环
var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; for (let key of Object.keys(p)){ console.log(`key: ${key} & value: ${p[key]}`) }
将 forEach() 与 Object.keys、Object.values、Object.entries 一起使用
var p = { "p1": "value1", "p2": "value2", "p3": "value3" }; Object.keys(p).forEach(key=>{ console.log(`${key} : ${p[key]}`); }); Object.values(p).forEach(value=>{ console.log(value); }); Object.entries(p).forEach(([key,value])=>{ console.log(`${key}:${value}`) })
使用纯 JavaScript 时,循环会非常有趣。似乎只有 ECMA6(新的 2015 JavaScript 规范)才能控制循环。不幸的是,在我写这篇文章时,浏览器和流行的集成开发环境 (IDE) 仍在努力完全支持新的花里胡哨。
下面是 ECMA6 之前的 JavaScript 对象循环的外观:
for (var key in object) {
if (p.hasOwnProperty(key)) {
var value = object[key];
console.log(key); // This is the key;
console.log(value); // This is the value;
}
}
另外,我知道这超出了这个问题的范围,但是在 2011 年,ECMAScript 5.1 只为数组添加了 forEach
方法,它基本上创建了一种新的改进方法来循环遍历数组,同时仍然使不可迭代的对象具有旧的冗长和混乱for
循环。但奇怪的是,这个新的 forEach
方法不支持 break
,这导致了各种其他问题。
基本上在 2011 年,除了许多流行的库(jQuery、Underscore 等)决定重新实现之外,没有真正可靠的循环 JavaScript 方法。
截至 2015 年,我们现在有了更好的开箱即用方式来循环(和中断)任何对象类型(包括数组和字符串)。当推荐成为主流时,JavaScript 中的循环最终会是这样的:
for (let [key, value] of Object.entries(object)) {
console.log(key); // This is the key;
console.log(value); // This is the value;
}
请注意,截至 2016 年 6 月 18 日,大多数浏览器将不支持上述代码。即使在 Chrome 中,您也需要启用此特殊标志才能使其工作:chrome://flags/#enable-javascript-harmony
在这成为新标准之前,仍然可以使用旧方法,但在流行的库中也有替代方法,甚至 lightweight alternatives 对于那些不使用任何这些库的人。
Uncaught TypeError: Object.entries is not a function
。它还没有在chrome中实现吗?
您可以为所有对象添加一个简单的 forEach 函数,这样您就可以自动循环遍历任何对象:
Object.defineProperty(Object.prototype, 'forEach', {
value: function (func) {
for (var key in this) {
if (!this.hasOwnProperty(key)) {
// skip loop if the property is from prototype
continue;
}
var value = this[key];
func(key, value);
}
},
enumerable: false
});
对于那些不喜欢“for ... in”方法的人:
Object.defineProperty(Object.prototype, 'forEach', {
value: function (func) {
var arr = Object.keys(this);
for (var i = 0; i < arr.length; i++) {
var key = arr[i];
func(key, this[key]);
}
},
enumerable: false
});
现在,您可以简单地调用:
p.forEach (function(key, value){
console.log ("Key: " + key);
console.log ("Value: " + value);
});
如果您不想与其他 forEach-Methods 发生冲突,您可以使用您的唯一名称命名它。
Object
)通常被认为是一种反模式,因为它很容易与其他代码发生冲突。所以伤口不建议这样做。
在可枚举的 JavaScript 对象上循环的一种好方法是使用 Object.keys
或 Object.entries
和 map
函数,这对于 ReactJS 来说可能很棒而且很常见。如下所示:
// assume items:
const items = {
first: { name: 'phone', price: 400 },
second: { name: 'tv', price: 300 },
third: { name: 'sofa', price: 250 },
};
对于循环并在 ReactJS
上显示一些 UI,如下所示:
~~~
<div>
{Object.entries(items).map(([key, ({ name, price })]) => (
<div key={key}>
<span>name: {name}</span>
<span>price: {price}</span>
</div>
))}
</div>
实际上,我使用了两次解构赋值,一次用于获取 key
,一次用于获取 name
和 price
。
<Fragment>
中不起作用,这是完美的解决方案。非常感谢
how for loops don't work inside <Fragment>
。它仍然有任何问题吗?如果确实如此,请留下问题并告诉我,我会回答。如果什么都没有,你现在没事了。请给 this post of me 点赞。谢谢。
在 ES6 中,我们有众所周知的符号来公开一些以前的内部方法,您可以使用它来定义迭代器如何为该对象工作:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3",
*[Symbol.iterator]() {
yield *Object.keys(this);
}
};
[...p] //["p1", "p2", "p3"]
这将给出与使用 for...in es6 循环相同的结果。
for(var key in p) {
console.log(key);
}
但是了解您现在使用 es6 的能力很重要!
Object.keys()
生成并在内存中分配的数组的内置数组迭代器......酷!
我会这样做,而不是在每个 for ... in
循环中检查 obj.hasOwnerProperty
。
var obj = {a : 1};
for(var key in obj){
//obj.hasOwnProperty(key) is not needed.
console.log(key);
}
//then check if anybody has messed the native object. Put this code at the end of the page.
for(var key in Object){
throw new Error("Please don't extend the native object");
}
从 ES06 开始,您可以将对象的值作为数组获取
let arrValues = Object.values( yourObject) ;
它返回对象值的数组,而不是从原型中提取值!!
和钥匙(在这里我已经回答了)
let arrKeys = Object.keys(yourObject);
var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"}, {"username":"ordermanageadmin_1","user_id":"3", "resource_id":"Magento_Sales::actions"}] for(var value in p) { for (var key in value) { if (p.hasOwnProperty(key)) { console.log(key + " -> " + p [钥匙]); } } }
json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -> " + json[i][key]); } } }