【发布时间】:2021-12-27 23:26:28
【问题描述】:
如果有 JavaScript 对象:
var objects={...};
假设它有 50 多个属性,不知道属性名称(即不知道“键”)如何在循环中获取每个属性值?
【问题讨论】:
-
读者注意:不要错过非常有见地的second answer
标签: javascript javascript-objects
如果有 JavaScript 对象:
var objects={...};
假设它有 50 多个属性,不知道属性名称(即不知道“键”)如何在循环中获取每个属性值?
【问题讨论】:
标签: javascript javascript-objects
根据您必须支持的浏览器,这可以通过多种方式完成。绝大多数浏览器都支持 ECMAScript 5 (ES5),但请注意,下面的许多示例使用 Object.keys,这在 IE compatibility table。
如果您必须支持旧版本的 IE,那么这是您的选择:
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var val = obj[key];
// use val
}
}
嵌套的if 确保您不会枚举对象原型链中的属性(这是您几乎肯定想要的行为)。你必须使用
Object.prototype.hasOwnProperty.call(obj, key) // ok
而不是
obj.hasOwnProperty(key) // bad
因为 ECMAScript 5+ 允许您使用 Object.create(null) 创建无原型对象,而这些对象将没有 hasOwnProperty 方法。顽皮的代码也可能产生覆盖hasOwnProperty 方法的对象。
您可以在任何支持 ECMAScript 5 及更高版本的浏览器中使用这些方法。这些从对象中获取值并避免枚举原型链。 obj 是你的对象:
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var val = obj[keys[i]];
// use val
}
如果你想要更紧凑的东西,或者你想小心循环中的函数,那么Array.prototype.forEach 是你的朋友:
Object.keys(obj).forEach(function (key) {
var val = obj[key];
// use val
});
下一个方法构建一个包含对象值的数组。这样方便循环。
var vals = Object.keys(obj).map(function (key) {
return obj[key];
});
// use vals array
如果您想让那些使用Object.keys 的人对null 安全(就像for-in 一样),那么您可以使用Object.keys(obj || {})...。
Object.keys 返回可枚举 属性。对于迭代简单对象,这通常就足够了。如果您需要使用具有不可枚举属性的东西,您可以使用Object.getOwnPropertyNames 代替Object.keys。
使用 ECMAScript 2015 更容易迭代数组。在循环中逐个处理值时,您可以利用这一点:
for (const key of Object.keys(obj)) {
const val = obj[key];
// use val
}
使用 ECMAScript 2015 fat-arrow 函数,将对象映射到值数组变得单行:
const vals = Object.keys(obj).map(key => obj[key]);
// use vals array
ECMAScript 2015 引入了Symbol,其实例可用作属性名称。要获取要枚举的对象的符号,请使用Object.getOwnPropertySymbols(这个函数就是为什么Symbol 不能用于创建私有属性)。来自 ECMAScript 2015 的新 Reflect API 提供了 Reflect.ownKeys,它返回属性名称(包括不可枚举的)和符号的列表。
数组推导在发布前已从 ECMAScript 6 中删除。在移除之前,解决方案应该是这样的:
const vals = [for (key of Object.keys(obj)) obj[key]];
// use vals array
ECMAScript 2016 添加了不影响该主题的功能。 ECMAScript 2017 规范增加了Object.values 和Object.entries。两者都返回数组(考虑到与Array.entries 的类比,这会让一些人感到惊讶)。 Object.values 可以按原样使用,也可以与for-of 循环一起使用。
const values = Object.values(obj);
// use values array or:
for (const val of Object.values(obj)) {
// use val
}
如果您想同时使用键和值,那么Object.entries 适合您。它生成一个填充有[key, value] 对的数组。您可以按原样使用它,或者(另请注意 ECMAScript 2015 解构赋值)在 for-of 循环中使用:
for (const [key, val] of Object.entries(obj)) {
// use key and val
}
Object.values垫片最后,正如 cmets 和 teh_senaus 在另一个答案中所指出的那样,将其中一个用作 shim 可能是值得的。不用担心,以下并没有改变原型,只是在Object 中添加了一个方法(危险性要小得多)。使用粗箭头函数,这也可以在一行中完成:
Object.values = obj => Object.keys(obj).map(key => obj[key]);
你现在可以像这样使用
// ['one', 'two', 'three']
var values = Object.values({ a: 'one', b: 'two', c: 'three' });
如果您想在原生 Object.values 存在时避免填充,那么您可以这样做:
Object.values = Object.values || (obj => Object.keys(obj).map(key => obj[key]));
注意您需要支持的浏览器/版本。以上在实现方法或语言功能的地方是正确的。例如,直到最近,对 ECMAScript 2015 的支持在 V8 中默认关闭,它支持 Chrome 等浏览器。在您打算支持的浏览器实现您需要的功能之前,应避免使用 ECMAScript 2015 中的功能。如果您使用 babel 将代码编译为 ECMAScript 5,那么您可以访问此答案中的所有功能。
【讨论】:
obj。我想创建一个辅助函数是不可避免的吗?像值(obj)这样的东西。
Object.values = obj => Object.keys(obj).map(key => obj[key]);
通过使用简单的for..in 循环:
for(var key in objects) {
var value = objects[key];
}
【讨论】:
enumerable 标志设置为false 的属性。这 - 除其他外 - 意味着您不会迭代任何类方法,但您将迭代以其他方式创建的方法。
这是一个用于将值放入数组的可重用函数。它也考虑了原型。
Object.values = function (obj) {
var vals = [];
for( var key in obj ) {
if ( obj.hasOwnProperty(key) ) {
vals.push(obj[key]);
}
}
return vals;
}
【讨论】:
Object 不是什么大问题(Object.keys 是一个常见的 shim),您可能正在考虑修改 Object 原型。
hasOwnProperty() 进行测试?没有该属性的对象的循环中如何迭代键?
如果你可以访问 Underscore.js,你可以像这样使用_.values 函数:
_.values({one : 1, two : 2, three : 3}); // return [1, 2, 3]
【讨论】:
ES5 Object.keys
var a = { a: 1, b: 2, c: 3 };
Object.keys(a).map(function(key){ return a[key] });
// result: [1,2,3]
【讨论】:
Object.values 是更简单的解决方案。
如果你真的想要一个值数组,我发现这比用 for ... in 循环构建一个数组更干净。
ECMA 5.1+
function values(o) { return Object.keys(o).map(function(k){return o[k]}) }
值得注意的是,在大多数情况下,您并不真的需要一个值数组,这样做会更快:
for(var k in o) something(o[k]);
这会遍历 Object o 的键。在每次迭代中,将 k 设置为 o 的键。
【讨论】:
你可以遍历键:
foo = {one:1, two:2, three:3};
for (key in foo){
console.log("foo["+ key +"]="+ foo[key]);
}
将输出:
foo[one]=1
foo[two]=2
foo[three]=3
【讨论】:
ECMA2017 起:
Object.values(obj) 会将所有属性值作为数组获取。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values
【讨论】:
该问题没有指定是否还需要继承和不可枚举的属性。
有a question for getting everything, inherited properties and non-enumerable properties also,Google 无法轻易找到。
如果我们要获取所有继承的和不可枚举的属性,我的解决方案是:
function getAllPropertyNames(obj) {
let result = new Set();
while (obj) {
Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
obj = Object.getPrototypeOf(obj);
}
return [...result];
}
然后遍历它们,只需使用 for-of 循环:
function getAllPropertyNames(obj) {
let result = new Set();
while (obj) {
Object.getOwnPropertyNames(obj).forEach(p => result.add(p));
obj = Object.getPrototypeOf(obj);
}
return [...result];
}
let obj = {
abc: 123,
xyz: 1.234,
foobar: "hello"
};
for (p of getAllPropertyNames(obj)) console.log(p);
【讨论】:
对于那些在 CofeeScript 时代早期适应的人,这里有另一个等价物。
val for key,val of objects
这可能比这更好,因为objects 可以简化为再次键入并降低可读性。
objects[key] for key of objects
【讨论】:
显然 - 正如我最近了解到的 - 这是最快的方法:
var objs = {...};
var objKeys = Object.keys(obj);
for (var i = 0, objLen = objKeys.length; i < objLen; i++) {
// do whatever in here
var obj = objs[objKeys[i]];
}
【讨论】:
使用以下 polyfill:
if(!Object.values){Object.values=obj=>Object.keys(obj).map(key=>obj[key])}
然后使用
Object.values(my_object)
3) 利润!
【讨论】:
const myObj = { a:1, b:2, c:3 }
获取所有值:
最短路径:
const myValues = Object.values(myObj)const myValues = Object.keys(myObj).map(key => myObj[key])
【讨论】:
我意识到我来晚了,但这里有一个 shim 用于新的 firefox 47 Object.values 方法
Object.prototype.values = Object.prototype.values || function(obj) {
return this.keys(obj).map(function(key){
return obj[key];
});
};
【讨论】:
Object.entries 做得更好。
var dataObject = {"a":{"title":"shop"}, "b":{"title":"home"}}
Object.entries(dataObject).map(itemArray => {
console.log("key=", itemArray[0], "value=", itemArray[1])
})
【讨论】:
使用:Object.values(),我们传入一个对象作为参数,并接收一个值数组作为返回值。
这将返回给定对象自己的可枚举属性值的数组。您将获得与使用 for in 循环相同的值,但没有 Prototype 上的属性。这个例子可能会让事情更清楚:
function person (name) {
this.name = name;
}
person.prototype.age = 5;
let dude = new person('dude');
for(let prop in dude) {
console.log(dude[prop]); // for in still shows age because this is on the prototype
} // we can use hasOwnProperty but this is not very elegant
// ES6 +
console.log(Object.values(dude));
// very concise and we don't show props on prototype
【讨论】:
const object1 = {
a: 'somestring',
b: 42
};
for (let [key, value] of Object.entries(object1)) {
console.log(`${key}: ${value}`);
}
// expected output:
// "a: somestring"
// "b: 42"
// order is not guaranteed
【讨论】:
这里有个类似PHP的array_values()的函数
function array_values(input) {
var output = [], key = '';
for ( key in input ) { output[output.length] = input[key]; }
return output;
}
如果您使用的是 ES6 或更高版本,以下是获取对象值的方法:
Array.from(values(obj));
【讨论】:
因为,Object.values(<object>) 将被内置在 ES7 &
在等待所有浏览器支持它之前,你可以将它包装在一个函数中:
Object.vals=(o)=>(Object.values)?Object.values(o):Object.keys(o).map((k)=>o[k])
然后:
Object.vals({lastname:'T',firstname:'A'})
// ['T','A']
【讨论】:
var objects={...}; this.getAllvalues = function () {
var vls = [];
for (var key in objects) {
vls.push(objects[key]);
}
return vls;
}
【讨论】:
在ECMAScript5中使用
keys = Object.keys(object);
否则如果您的浏览器不支持,请使用众所周知的for..in loop
for (key in object) {
// your code here
}
【讨论】:
object[key] 在循环中获取值。
for..in(和hasOwnProperty)来完成,所以它并没有真正获得任何东西..我希望ECMAScript 5th定义Object.pairs(和Object.items为@987654328 @),但可惜不是。
现在我使用Dojo Toolkit,因为旧版浏览器不支持Object.values。
require(['dojox/lang/functional/object'], function(Object) {
var obj = { key1: '1', key2: '2', key3: '3' };
var values = Object.values(obj);
console.log(values);
});
输出:
['1', '2', '3']
【讨论】:
使用
console.log(variable)
如果您使用 google chrome 打开控制台,请使用 Ctrl+Shift+j
转到 >> 控制台
【讨论】: