我有一个JavaScript对象,如下所示:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
我如何循环遍历p的所有元素(p1、p2、p3…)并获取它们的键和值?
我有一个JavaScript对象,如下所示:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
我如何循环遍历p的所有元素(p1、p2、p3…)并获取它们的键和值?
当前回答
如果还想迭代非可枚举财产,可以使用Object.getOwnPropertyNames(obj)返回直接在给定对象上找到的所有财产(可枚举或不可枚举)的数组。
var obj=对象.创建({}{//不可枚举属性获取食物:{value:函数(){return this.foo;},可枚举:false}});obj.foo=1;//可枚举属性Object.getOwnPropertyNames(obj).forEach(函数(名称){document.write(name+':'+obj[name]+'<br/>');});
其他回答
单行和更可读的代码可以。。
Object.entries(myObject).map(([key, value]) => console.log(key, value))
考虑到ES6,我想添加自己的一勺糖,并提供另一种方法来迭代对象的财产。
由于纯JS对象不能立即迭代,因此我们无法使用。。用于迭代其内容的循环。但没有人能阻止我们使其可迭代。
让我们有书的对象。
let book = {
title: "Amazing book",
author: "Me",
pages: 3
}
book[Symbol.iterator] = function(){
let properties = Object.keys(this); // returns an array with property names
let counter = 0;
let isDone = false;
let next = () => {
if(counter >= properties.length){
isDone = true;
}
return { done: isDone, value: this[properties[counter++]] }
}
return { next };
}
既然我们做到了,我们可以这样使用它:
for(let pValue of book){
console.log(pValue);
}
------------------------
Amazing book
Me
3
或者如果你知道ES6发电机的功率,那么你当然可以让上面的代码更短。
book[Symbol.iterator] = function *(){
let properties = Object.keys(this);
for (let p of properties){
yield this[p];
}
}
当然,通过在原型级别上使Object可迭代,您可以对所有对象应用这样的行为。
Object.prototype[Symbol.iterator] = function() {...}
此外,符合可迭代协议的对象可以与新的ES2015特性扩展运算符一起使用,因此我们可以将对象属性值作为数组读取。
let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]
或者可以使用析构函数赋值:
let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3
您可以使用我上面提供的所有代码查看JSFiddle。
有两个选项:
您可以使用。。在那里
变量p={“p1”:“值1”,“p2”:“值2”,“p3”:“值3”};for(p中的常量项){console.log(`key=${item},value=${p[item]}`);}
您还可以调用Object.entries()来创建一个包含所有可枚举财产的数组。之后,您可以使用map、foreach或for循环浏览它。。属于
变量p={“p1”:“值1”,“p2”:“值2”,“p3”:“值3”};Object.entries(p).map(item=>{console.log(项)})
变量p={“p1”:“值1”,“p2”:“值2”,“p3”:“值3”};Object.entries(p).forEach(item=>{console.log(项)})
变量p={“p1”:“值1”,“p2”:“值2”,“p3”:“值3”};for(Object.entries(p)的常量项){console.log(项)}
有关Object.entries()的更多信息,请参见此处
前言:
对象财产可以是自己的(属性在对象本身上),也可以是继承的(不在对象本身或其原型上)。对象财产可以是可枚举的或非可枚举的。在许多属性枚举/数组中,不包含非数财产。属性名称可以是字符串或符号。许多属性枚举/数组都没有包含名称为Symbol的财产。
2018年,您可以选择循环访问对象的财产(以下是一些示例):
for-in[MDN,spec]-一种循环结构,循环遍历对象的可枚举财产的名称,包括名称为字符串的继承属性keys[MDN,spec]-一个函数,提供对象自己的可枚举财产的名称数组,这些属性的名称是字符串。Object.values[MDN,spec]-提供对象自身可枚举财产值数组的函数。Object.entries[MDN,spec]-提供对象自身可枚举财产的名称和值数组的函数(数组中的每个条目都是[name,value]数组)。Object.getOwnPropertyNames[MDN,spec]-一个函数,提供对象自己的财产(即使是不可枚举的属性)的名称数组,这些属性的名称是字符串。Object.getOwnPropertySymbols[MDN,spec]-一个函数,提供对象自己的财产(即使是不可枚举的属性)的名称数组,其名称为Symbols。Reflect.ownKeys[MDN,spec]-一个函数,提供对象自己的财产(即使是非枚举属性)的名称数组,无论这些名称是字符串还是符号。如果需要对象的所有财产,包括非枚举继承的属性,则需要使用循环和object.getPrototypeOf[MDN,spec],并在原型链中的每个对象上使用object.getOwnPropertyNames、object.getOwnPropertySymbols或Reflect.ownKeys(此答案底部的示例)。
对于除in之外的所有元素,您将在数组上使用某种循环构造(for、for、forEach等)。
示例:
中的:
//要从中继承的原型对象,具有名为property的字符串常量p={answer:42};//我们将看到的对象继承自`p`const o=对象创建(p);//名为property的字符串o.question=“生命、宇宙和一切”;//名为属性的符号o[Symbol(“author”)]=“Douglas Adams”;for(o中的常量名称){常量值=o[名称];console.log(`${name}=${value}`);}
Object.keys(带有for of循环,但可以使用任何循环构造):
//要从中继承的原型对象,具有名为property的字符串常量p={answer:42};//我们将看到的对象继承自`p`const o=对象创建(p);//名为property的字符串o.question=“生命、宇宙和一切”;//名为属性的符号o[Symbol(“author”)]=“Douglas Adams”;for(Object.keys(o)的常量名称){常量值=o[名称];console.log(`${name}=${value}`);}
对象值:
//要从中继承的原型对象,具有名为property的字符串常量p={answer:42};//我们将看到的对象继承自`p`const o=对象创建(p);//名为property的字符串o.question=“生命、宇宙和一切”;//名为属性的符号o[Symbol(“author”)]=“Douglas Adams”;for(Object.values(o)的常量值){console.log(`${value}`);}
对象条目:
//要从中继承的原型对象,具有名为property的字符串常量p={answer:42};//我们将看到的对象继承自`p`const o=对象创建(p);//名为property的字符串o.question=“生命、宇宙和一切”;//名为属性的符号o[Symbol(“author”)]=“Douglas Adams”;for(Object.entries(o)的常量[名称,值]){console.log(`${name}=${value}`);}
Object.getOwnPropertyName:
//要从中继承的原型对象,具有名为property的字符串常量p={answer:42};//我们将看到的对象继承自`p`const o=对象创建(p);//名为property的字符串o.question=“生命、宇宙和一切”;//名为属性的符号o[Symbol(“author”)]=“Douglas Adams”;for(Object.getOwnPropertyNames(o)的常量名称){常量值=o[名称];console.log(`${name}=${value}`);}
Object.getOwnPropertySymbols:
//要从中继承的原型对象,具有名为property的字符串常量p={answer:42};//我们将看到的对象继承自`p`const o=对象创建(p);//名为property的字符串o.question=“生命、宇宙和一切”;//名为属性的符号o[Symbol(“author”)]=“Douglas Adams”;for(Object.getOwnPropertySymbol(o)的常量名称){常量值=o[名称];console.log(`${String(name)}=${value}`);}
反射所有键:
//要从中继承的原型对象,具有名为property的字符串常量p={answer:42};//我们将看到的对象继承自`p`const o=对象创建(p);//名为property的字符串o.question=“生命、宇宙和一切”;//名为属性的符号o[Symbol(“author”)]=“Douglas Adams”;for(Reflect.ownKeys(o)的常量名称){常量值=o[名称];console.log(`${String(name)}=${value}`);}
所有财产,包括继承的非枚举属性:
//要从中继承的原型对象,具有名为property的字符串常量p={answer:42};//我们将看到的对象继承自`p`const o=对象创建(p);//名为property的字符串o.question=“生命、宇宙和一切”;//名为属性的符号o[Symbol(“author”)]=“Douglas Adams”;for(让深度=0,当前=o;当前;++深度,当前=Object.getPrototypeOf(当前)){for(Reflect.ownKeys(当前)的常量名称){常量值=o[名称];console.log(`[${depth}]${String(name)}=${字符串(value)}`);}}.作为控制台包装{最大高度:100%!重要的}
有趣的是,这些答案中的人都提到了Object.keys()和for。。。但从未组合:
var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
console.log(key + ':' + map[key]);
你不能只是为了。。。因为它不是迭代器,并且。。。index或.forEach()调用Object.keys()是丑陋/低效的。我很高兴大多数人都没有。。。in(有或没有检查.hasOwnProperty()),因为这也有点混乱,所以除了我上面的答案之外,我想说。。。
您可以使普通对象关联迭代!行为就像地图一样,直接使用了。。。属于DEMO在Chrome和FF中工作(我假设只有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]);
事实上,有了这个填充程序,如果您仍然想利用Map的其他功能(不填充它们),但仍然想使用整洁的对象表示法,因为对象现在是可迭代的,那么您现在只需从中创建一个Map即可!
//shown in demo
var realMap = new Map({well:'hello', there:'!'});
对于那些不喜欢填充,或者不喜欢处理原型的人,可以在窗口上创建函数,然后调用类似于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:'!'}))
or
for (let pair of getObjIterator(ordinaryObject))
这没有理由不起作用。
欢迎来到未来。