How to access the first property of a Javascript object? - javascript

Is there an elegant way to access the first property of an object...
where you don't know the name of your properties
without using a loop like for .. in or jQuery's $.each
For example, I need to access foo1 object without knowing the name of foo1:
var example = {
foo1: { /* stuff1 */},
foo2: { /* stuff2 */},
foo3: { /* stuff3 */}
};

var obj = { first: 'someVal' };
obj[Object.keys(obj)[0]]; //returns 'someVal'
Object.values(obj)[0]; // returns 'someVal'
Using this you can access also other properties by indexes. Be aware tho! Object.keys or Object.values return order is not guaranteed as per ECMAScript however unofficially it is by all major browsers implementations, please read https://stackoverflow.com/a/23202095 for details on this.

Try the for … in loop and break after the first iteration:
for (var prop in object) {
// object[prop]
break;
}

You can also do Object.values(example)[0].

You can use Object.values() to access values of an object:
var obj = { first: 'someVal' };
Object.values(obj)[0]; // someVal

Use Object.keys to get an array of the properties on an object. Example:
var example = {
foo1: { /* stuff1 */},
foo2: { /* stuff2 */},
foo3: { /* stuff3 */}
};
var keys = Object.keys(example); // => ["foo1", "foo2", "foo3"] (Note: the order here is not reliable)
Documentation and cross-browser shim provided here. An example of its use can be found in another one of my answers here.
Edit: for clarity, I just want to echo what was correctly stated in other answers: the key order in JavaScript objects is undefined.

A one-liner version:
var val = example[function() { for (var k in example) return k }()];

There isn't a "first" property. Object keys are unordered.
If you loop over them with for (var foo in bar) you will get them in some order, but it may change in future (especially if you add or remove other keys).

The top answer could generate the whole array and then capture from the list. Here is an another effective shortcut
var obj = { first: 'someVal' };
Object.entries(obj)[0][1] // someVal

Solution with lodash library:
_.find(example) // => {name: "foo1"}
but there is no guarantee of the object properties internal storage order because it depends on javascript VM implementation.

Here is a cleaner way of getting the first key:
var object = {
foo1: 'value of the first property "foo1"',
foo2: { /* stuff2 */},
foo3: { /* stuff3 */}
};
let [firstKey] = Object.keys(object)
console.log(firstKey)
console.log(object[firstKey])

if someone prefers array destructuring
const [firstKey] = Object.keys(object);

No. An object literal, as defined by MDN is:
a list of zero or more pairs of property names and associated values of an object, enclosed in curly braces ({}).
Therefore an object literal is not an array, and you can only access the properties using their explicit name or a for loop using the in keyword.

To get the first key name in the object you can use:
var obj = { first: 'someVal' };
Object.keys(obj)[0]; //returns 'first'
Returns a string, so you cant access nested objects if there were, like:
var obj = { first: { someVal : { id : 1} }; Here with that solution you can't access id.
The best solution if you want to get the actual object is using lodash like:
obj[_.first(_.keys(obj))].id
To return the value of the first key, (if you don't know exactly the first key name):
var obj = { first: 'someVal' };
obj[Object.keys(obj)[0]]; //returns 'someVal'
if you know the key name just use:
obj.first
or
obj['first']

This has been covered here before.
The concept of first does not apply to object properties, and the order of a for...in loop is not guaranteed by the specs, however in practice it is reliably FIFO except critically for chrome (bug report). Make your decisions accordingly.

I don't recommend you to use Object.keys since its not supported in old IE versions. But if you really need that, you could use the code above to guarantee the back compatibility:
if (!Object.keys) {
Object.keys = (function () {
var hasOwnProperty = Object.prototype.hasOwnProperty,
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
dontEnums = [
'toString',
'toLocaleString',
'valueOf',
'hasOwnProperty',
'isPrototypeOf',
'propertyIsEnumerable',
'constructor'
],
dontEnumsLength = dontEnums.length;
return function (obj) {
if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
var result = [];
for (var prop in obj) {
if (hasOwnProperty.call(obj, prop)) result.push(prop);
}
if (hasDontEnumBug) {
for (var i=0; i < dontEnumsLength; i++) {
if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
}
}
return result;
}})()};
Feature Firefox (Gecko)4 (2.0) Chrome 5 Internet Explorer 9 Opera 12 Safari 5
More info: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys
But if you only need the first one, we could arrange a shorter solution like:
var data = {"key1":"123","key2":"456"};
var first = {};
for(key in data){
if(data.hasOwnProperty(key)){
first.key = key;
first.content = data[key];
break;
}
}
console.log(first); // {key:"key",content:"123"}

If you need to access "the first property of an object", it might mean that there is something wrong with your logic. The order of an object's properties should not matter.

A more efficient way to do this, without calling Object.keys() or Object.values() which returns an array:
Object.prototype.firstKey = function () {
for (const k in this) {
if (Object.prototype.hasOwnProperty.call(this, k)) return k;
}
return null;
};
Then you can use it like:
const obj = {a: 1, b: 2, c: 3}
console.log(obj.firstKey()) //=> 'a'
This doesn't necessarily return the first key, see Elements order in a "for (… in …)" loop

we can also do with this approch.
var example = {
foo1: { /* stuff1 */},
foo2: { /* stuff2 */},
foo3: { /* stuff3 */}
};
Object.entries(example)[0][1];

This is an old question but most of the solutions assume that we know the attribute's name which it is not the case for example if you are trying to visualize data from files that the user can upload or similar cases.
This is a simple function that I use and works in both cases that you know the variable and if not it will return the first attribute of the object (sorted alphabetically)
The label function receives an object d and extract the key if exits, otherwise returns the first attribute of the object.
const data = [
{ label: "A", value: 10 },
{ label: "B", value: 15 },
{ label: "C", value: 20 },
{ label: "D", value: 25 },
{ label: "E", value: 30 }
]
const keys = ['label', 0, '', null, undefined]
const label = (d, k) => k ? d[k] : Object.values(d)[0]
data.forEach(d => {
console.log(`first: ${label(d)}, label: ${label(d, keys[0])}`)
})
keys.forEach(k => {
console.log(`label of ${k}: ${label(data[0], k)}`)
})
For values like 0, '', null, and undefined will return the first element of the array.

this is my solution
const dataToSend = {email:'king#gmail.com',password:'12345'};
const formData = new FormData();
for (let i = 0; i < Object.keys(dataToSend).length; i++) {
formData.append(Object.keys(dataToSend)[i],
Object.values(dataToSend)[i]);
}
console.log(formData);

Any reason not to do this?
> example.map(x => x.name);
(3) ["foo1", "foo2", "foo3"]

Basic syntax to iterate through key-value gracefully
const object1 = {
a: 'somestring',
b: 42
};
for (const [key, value] of Object.entries(object1)) {
console.log(`${key}: ${value}`);
}
// expected output:
// "a: somestring"
// "b: 42"

As others have pointed out, if the order of properties is important, storing them in an object is not a good idea. Instead, you should use an array via square brackets. E.g.,
var example = [ {/* stuff1 */}, { /* stuff2 */}, { /* stuff3 */}];
var first = example[0];
Note that you lose the 'foo' identifiers. But you could add a name property to the contained objects:
var example = [
{name: 'foo1', /* stuff1 */},
{name: 'foo2', /* stuff2 */},
{name: 'foo3', /* stuff3 */}
];
var whatWasFirst = example[0].name;
For those seeking an answer to a similar question, namely: "How do I find one or more properties that match a certain pattern?", I'd recommend using Object.keys(). To extend benekastah's answer:
for (const propName of Object.keys(example)) {
if (propName.startsWith('foo')) {
console.log(`Found propName ${propName} with value ${example[propName]}`);
break;
}
}

Related

How to `reduce` over an object?

I wonder how to use some reduce logic over an object rather than an array. Something like iterating over tuples represented by
[ object_property, property_value ]).
I tried some code like
var obj = { foo: 'bar', bar: 'baz' };
Array.prototype.reduce.call(obj, function(prev, val) {
console.log('new iteration');
// whatever code ...
return prev;
}, []);
but it doesn't perform any iteration. I can't understand why.
Maybe because the object properties are not enumerable?
Is there any way to run a reduce function on an object?
Note: There is no specific final purpose; I am exploring what's possible or what might be better patterns.
Array methods like reduce() can only operate on arrays or array-like objects (with length and numeric properties).
You can call Object.values() to get an array of an object's property values.
Several mistakes.
obj is not an array. Use .values()
The result of prev.push is not the array, is the result of the push method which is 1 (integer);
there is no var to get the final result.
Here is a working example:
var obj = { foo: 'bar', bar: 'baz' };
var res = Array.prototype.reduce.call(Object.values(obj), function(prev, val) {
prev.push(val);
return prev;
}, []);
console.log(res);
I don't know why you are using Array.prototype.reduce.call. There's no need to call it this way. Maybe you're experimenting with js or something.
Also prev is not a good name. Remember that it accumulates values, it's not just the previous interaction's value. Anyway, this is an easier way to do it:
var obj = { foo: 'bar', bar: 'baz' };
var res = Object.values(obj).reduce((acc, val)=>{
acc.push(val);
return acc;
}, []);
console.log(res);
But if this is the answer you want, reduce is not needed at all. Look:
var obj = { foo: 'bar', bar: 'baz' };
console.log(Object.values(obj));
You can run reduce() method on the array returned by Object.keys() function. It looks like this:
var obj = { foo: 'fooValue', bar: 'barValue' };
var str = Object.keys(obj).reduce((accum, key)=>{
return accum + obj[key];
}, '');
// str = 'fooValuebarValue';
You can use
Object.keys(obj) which will give you array of property names on that array you can apply any array method(predefined)
like this
var obj = { foo: 'bar', bar: 'baz' };
var prev=[] //let say prev is array in which you want to store some property value
Object.keys(obj).reduce(function(element) {
// you can have condition here as well
prev.push(obj[element]);
});
but be careful if you just want to populate another array then you can use other array method like filter,map,forEach(just for learning purpose because it similar to for loop)
it would make sense.

ES6 for-of loop in map key value [duplicate]

This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed last year.
I have a dictionary that has the format of
dictionary = {0: {object}, 1:{object}, 2:{object}}
How can I iterate through this dictionary by doing something like
for ((key, value) in dictionary) {
//Do stuff where key would be 0 and value would be the object
}
tl;dr
In ECMAScript 2017, just call Object.entries(yourObj).
In ECMAScript 2015, it is possible with Maps.
In ECMAScript 5, it is not possible.
ECMAScript 2017
ECMAScript 2017 introduced a new Object.entries function. You can use this to iterate the object as you wanted.
'use strict';
const object = {'a': 1, 'b': 2, 'c' : 3};
for (const [key, value] of Object.entries(object)) {
console.log(key, value);
}
Output
a 1
b 2
c 3
ECMAScript 2015
In ECMAScript 2015, there is not Object.entries but you can use Map objects instead and iterate over them with Map.prototype.entries. Quoting the example from that page,
var myMap = new Map();
myMap.set("0", "foo");
myMap.set(1, "bar");
myMap.set({}, "baz");
var mapIter = myMap.entries();
console.log(mapIter.next().value); // ["0", "foo"]
console.log(mapIter.next().value); // [1, "bar"]
console.log(mapIter.next().value); // [Object, "baz"]
Or iterate with for..of, like this
'use strict';
var myMap = new Map();
myMap.set("0", "foo");
myMap.set(1, "bar");
myMap.set({}, "baz");
for (const entry of myMap.entries()) {
console.log(entry);
}
Output
[ '0', 'foo' ]
[ 1, 'bar' ]
[ {}, 'baz' ]
Or
for (const [key, value] of myMap.entries()) {
console.log(key, value);
}
Output
0 foo
1 bar
{} baz
ECMAScript 5:
No, it's not possible with objects.
You should either iterate with for..in, or Object.keys, like this
for (var key in dictionary) {
// check if the property/key is defined in the object itself, not in parent
if (dictionary.hasOwnProperty(key)) {
console.log(key, dictionary[key]);
}
}
Note: The if condition above is necessary only if you want to iterate over the properties which are the dictionary object's very own. Because for..in will iterate through all the inherited enumerable properties.
Or
Object.keys(dictionary).forEach(function(key) {
console.log(key, dictionary[key]);
});
Try this:
dict = {0:{1:'a'}, 1:{2:'b'}, 2:{3:'c'}}
for (var key in dict){
console.log( key, dict[key] );
}
0 Object { 1="a"}
1 Object { 2="b"}
2 Object { 3="c"}
WELCOME TO 2020 *Drools in ES6*
Theres some pretty old answers in here - take advantage of destructuring. In my opinion this is without a doubt the nicest (very readable) way to iterate an object.
const myObject = {
nick: 'cage',
phil: 'murray',
};
Object.entries(myObject).forEach(([k,v]) => {
console.log("The key: ", k)
console.log("The value: ", v)
})
Edit:
As mentioned by Lazerbeak, map allows you to cycle an object and use the key and value to make an array.
const myObject = {
nick: 'cage',
phil: 'murray',
};
const myArray = Object.entries(myObject).map(([k, v]) => {
return `The key '${k}' has a value of '${v}'`;
});
console.log(myArray);
Edit 2:
To explain what is happening in the line of code:
Object.entries(myObject).forEach(([k,v]) => {}
Object.entries() converts our object to an array of arrays:
[["nick", "cage"], ["phil", "murray"]]
Then we use forEach on the outer array:
1st loop: ["nick", "cage"]
2nd loop: ["phil", "murray"]
Then we "destructure" the value (which we know will always be an array) with ([k,v]) so k becomes the first name and v becomes the last name.
The Object.entries() method has been specified in ES2017 (and is supported in all modern browsers):
for (const [ key, value ] of Object.entries(dictionary)) {
// do something with `key` and `value`
}
Explanation:
Object.entries() takes an object like { a: 1, b: 2, c: 3 } and turns it into an array of key-value pairs: [ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ].
With for ... of we can loop over the entries of the so created array.
Since we are guaranteed that each of the so iterated array items is itself a two-entry array, we can use destructuring to directly assign variables key and value to its first and second item.
Try this:
var value;
for (var key in dictionary) {
value = dictionary[key];
// your code here...
}
You can do something like this :
dictionary = {'ab': {object}, 'cd':{object}, 'ef':{object}}
var keys = Object.keys(dictionary);
for(var i = 0; i < keys.length;i++){
//keys[i] for key
//dictionary[keys[i]] for the value
}
I think the fast and easy way is
Object.entries(event).forEach(k => {
console.log("properties ... ", k[0], k[1]); });
just check the documentation
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
using swagger-ui.js
you can do this -
_.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
console.log(n, key);
});
You can use below script.
var obj={1:"a",2:"b",c:"3"};
for (var x=Object.keys(obj),i=0;i<x.length,key=x[i],value=obj[key];i++){
console.log(key,value);
}
outputs
1 a
2 b
c 3
As an improvement to the accepted answer, in order to reduce nesting, you could do this instead, provided that the key is not inherited:
for (var key in dictionary) {
if (!dictionary.hasOwnProperty(key)) {
continue;
}
console.log(key, dictionary[key]);
}
Edit: info about Object.hasOwnProperty here
You can use JavaScript forEach Loop:
myMap.forEach((value, key) => {
console.log('value: ', value);
console.log('key: ', key);
});

How to iterate (keys, values) in JavaScript? [duplicate]

This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed last year.
I have a dictionary that has the format of
dictionary = {0: {object}, 1:{object}, 2:{object}}
How can I iterate through this dictionary by doing something like
for ((key, value) in dictionary) {
//Do stuff where key would be 0 and value would be the object
}
tl;dr
In ECMAScript 2017, just call Object.entries(yourObj).
In ECMAScript 2015, it is possible with Maps.
In ECMAScript 5, it is not possible.
ECMAScript 2017
ECMAScript 2017 introduced a new Object.entries function. You can use this to iterate the object as you wanted.
'use strict';
const object = {'a': 1, 'b': 2, 'c' : 3};
for (const [key, value] of Object.entries(object)) {
console.log(key, value);
}
Output
a 1
b 2
c 3
ECMAScript 2015
In ECMAScript 2015, there is not Object.entries but you can use Map objects instead and iterate over them with Map.prototype.entries. Quoting the example from that page,
var myMap = new Map();
myMap.set("0", "foo");
myMap.set(1, "bar");
myMap.set({}, "baz");
var mapIter = myMap.entries();
console.log(mapIter.next().value); // ["0", "foo"]
console.log(mapIter.next().value); // [1, "bar"]
console.log(mapIter.next().value); // [Object, "baz"]
Or iterate with for..of, like this
'use strict';
var myMap = new Map();
myMap.set("0", "foo");
myMap.set(1, "bar");
myMap.set({}, "baz");
for (const entry of myMap.entries()) {
console.log(entry);
}
Output
[ '0', 'foo' ]
[ 1, 'bar' ]
[ {}, 'baz' ]
Or
for (const [key, value] of myMap.entries()) {
console.log(key, value);
}
Output
0 foo
1 bar
{} baz
ECMAScript 5:
No, it's not possible with objects.
You should either iterate with for..in, or Object.keys, like this
for (var key in dictionary) {
// check if the property/key is defined in the object itself, not in parent
if (dictionary.hasOwnProperty(key)) {
console.log(key, dictionary[key]);
}
}
Note: The if condition above is necessary only if you want to iterate over the properties which are the dictionary object's very own. Because for..in will iterate through all the inherited enumerable properties.
Or
Object.keys(dictionary).forEach(function(key) {
console.log(key, dictionary[key]);
});
Try this:
dict = {0:{1:'a'}, 1:{2:'b'}, 2:{3:'c'}}
for (var key in dict){
console.log( key, dict[key] );
}
0 Object { 1="a"}
1 Object { 2="b"}
2 Object { 3="c"}
WELCOME TO 2020 *Drools in ES6*
Theres some pretty old answers in here - take advantage of destructuring. In my opinion this is without a doubt the nicest (very readable) way to iterate an object.
const myObject = {
nick: 'cage',
phil: 'murray',
};
Object.entries(myObject).forEach(([k,v]) => {
console.log("The key: ", k)
console.log("The value: ", v)
})
Edit:
As mentioned by Lazerbeak, map allows you to cycle an object and use the key and value to make an array.
const myObject = {
nick: 'cage',
phil: 'murray',
};
const myArray = Object.entries(myObject).map(([k, v]) => {
return `The key '${k}' has a value of '${v}'`;
});
console.log(myArray);
Edit 2:
To explain what is happening in the line of code:
Object.entries(myObject).forEach(([k,v]) => {}
Object.entries() converts our object to an array of arrays:
[["nick", "cage"], ["phil", "murray"]]
Then we use forEach on the outer array:
1st loop: ["nick", "cage"]
2nd loop: ["phil", "murray"]
Then we "destructure" the value (which we know will always be an array) with ([k,v]) so k becomes the first name and v becomes the last name.
The Object.entries() method has been specified in ES2017 (and is supported in all modern browsers):
for (const [ key, value ] of Object.entries(dictionary)) {
// do something with `key` and `value`
}
Explanation:
Object.entries() takes an object like { a: 1, b: 2, c: 3 } and turns it into an array of key-value pairs: [ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ].
With for ... of we can loop over the entries of the so created array.
Since we are guaranteed that each of the so iterated array items is itself a two-entry array, we can use destructuring to directly assign variables key and value to its first and second item.
Try this:
var value;
for (var key in dictionary) {
value = dictionary[key];
// your code here...
}
You can do something like this :
dictionary = {'ab': {object}, 'cd':{object}, 'ef':{object}}
var keys = Object.keys(dictionary);
for(var i = 0; i < keys.length;i++){
//keys[i] for key
//dictionary[keys[i]] for the value
}
I think the fast and easy way is
Object.entries(event).forEach(k => {
console.log("properties ... ", k[0], k[1]); });
just check the documentation
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
using swagger-ui.js
you can do this -
_.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
console.log(n, key);
});
You can use below script.
var obj={1:"a",2:"b",c:"3"};
for (var x=Object.keys(obj),i=0;i<x.length,key=x[i],value=obj[key];i++){
console.log(key,value);
}
outputs
1 a
2 b
c 3
As an improvement to the accepted answer, in order to reduce nesting, you could do this instead, provided that the key is not inherited:
for (var key in dictionary) {
if (!dictionary.hasOwnProperty(key)) {
continue;
}
console.log(key, dictionary[key]);
}
Edit: info about Object.hasOwnProperty here
You can use JavaScript forEach Loop:
myMap.forEach((value, key) => {
console.log('value: ', value);
console.log('key: ', key);
});

Create a dynamic nested object from array of properties

This sounds like a simple task, but I can't quite figure it out: I have an array :
var array = ['opt1','sub1','subsub1','subsubsub1']
From that I want to generate the following objects:
{
opt1:{
sub1:{
subsub1:{
subsubsub1:{}
}
}
}
}
I have a way to do it, making a string and using eval, but I'm looking to avoid that, any idea?
You could use reduce:
var array = ['opt1','sub1','subsub1','subsubsub1'];
var object = {};
array.reduce(function(o, s) { return o[s] = {}; }, object);
console.log(object);
But this was only introduced in ECMAScript 5.1, so it won't be supported in some older browsers. If you want something that will be supported by legacy browsers, you could use the polyfill technique described in the MDN article above, or a simple for-loop, like this:
var array = ['opt1','sub1','subsub1','subsubsub1'];
var object = {}, o = object;
for(var i = 0; i < array.length; i++) {
o = o[array[i]] = {};
}
console.log(object);
You can use reduceRight to transform the array into a 'chain' of objects:
const array = ['a', 'b', 'c'];
const object = array.reduceRight((obj, next) => ({[next]: obj}), {});
// Example:
console.log(object); // {"a":{"b":{"c":{}}}}
you could use lodash set function
_.set(yourObject, 'a.b.c')
You can use the following Function
function arr2nestedObject(myArray){
var cp_myArray = myArray;
var lastobj = {};
while(cp_myArray.length>0){
newobj = {};
var prop = cp_myArray.pop();
newobj[prop] = lastobj;
lastobj = newobj;
}
return lastobj;
}
The following code:
var myArray = ["personal-information", "address", "street",'Great-Success'];
console.log(JSON.stringify(arr2nestedObject(myArray),undefined,2));
Would Produce the Following Output:
{
"personal-information": {
"address": {
"street": {
"Great-Success": {}
}
}
}
}
Please let me know if that was what you meant.
Kind Regards.
As #p.s.w.g answer is a very good answer with pure js, but if you want an alternative with in a descriptive and functional way of that and set a value for final nested prop, you can use ramdajs assocPath https://ramdajs.com/docs/#assocPath like below:
var array = ['opt1','sub1','subsub1','subsubsub1'];
R.assocPath(array, "the value", {});
more details:
Makes a shallow clone of an object, setting or overriding the nodes
required to create the given path, and placing the specific value at
the tail end of that path. Note that this copies and flattens
prototype properties onto the new object as well. All non-primitive
properties are copied by reference.
examples:
R.assocPath(['a', 'b', 'c'], 42, {a: {b: {c: 0}}}); //=> {a: {b: {c: 42}}}
// Any missing or non-object keys in path will be overridden
R.assocPath(['a', 'b', 'c'], 42, {a: 5}); //=> {a: {b: {c: 42}}}

Get array of object's keys

I would like to get the keys of a JavaScript object as an array, either in jQuery or pure JavaScript.
Is there a less verbose way than this?
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
keys.push(key);
}
Use Object.keys:
var foo = {
'alpha': 'puffin',
'beta': 'beagle'
};
var keys = Object.keys(foo);
console.log(keys) // ['alpha', 'beta']
// (or maybe some other order, keys are unordered).
This is an ES5 feature. This means it works in all modern browsers but will not work in legacy browsers.
The ES5-shim has a implementation of Object.keys you can steal
You can use jQuery's $.map.
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' },
keys = $.map(foo, function(v, i){
return i;
});
Of course, Object.keys() is the best way to get an Object's keys. If it's not available in your environment, it can be trivially shimmed using code such as in your example (except you'd need to take into account your loop will iterate over all properties up the prototype chain, unlike Object.keys()'s behaviour).
However, your example code...
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
for (var key in foo) {
keys.push(key);
}
jsFiddle.
...could be modified. You can do the assignment right in the variable part.
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [], i = 0;
for (keys[i++] in foo) {}
jsFiddle.
Of course, this behaviour is different to what Object.keys() actually does (jsFiddle). You could simply use the shim on the MDN documentation.
In case you're here looking for something to list the keys of an n-depth nested object as a flat array:
const getObjectKeys = (obj, prefix = '') => {
return Object.entries(obj).reduce((collector, [key, val]) => {
const newKeys = [ ...collector, prefix ? `${prefix}.${key}` : key ]
if (Object.prototype.toString.call(val) === '[object Object]') {
const newPrefix = prefix ? `${prefix}.${key}` : key
const otherKeys = getObjectKeys(val, newPrefix)
return [ ...newKeys, ...otherKeys ]
}
return newKeys
}, [])
}
console.log(getObjectKeys({a: 1, b: 2, c: { d: 3, e: { f: 4 }}}))
I don't know about less verbose but I was inspired to coerce the following onto one line by the one-liner request, don't know how Pythonic it is though ;)
var keys = (function(o){var ks=[]; for(var k in o) ks.push(k); return ks})(foo);
Summary
For getting all of the keys of an Object you can use Object.keys(). Object.keys() takes an object as an argument and returns an array of all the keys.
Example:
const object = {
a: 'string1',
b: 42,
c: 34
};
const keys = Object.keys(object)
console.log(keys);
console.log(keys.length) // we can easily access the total amount of properties the object has
In the above example we store an array of keys in the keys const. We then can easily access the amount of properties on the object by checking the length of the keys array.
Getting the values with: Object.values()
The complementary function of Object.keys() is Object.values(). This function takes an object as an argument and returns an array of values. For example:
const object = {
a: 'random',
b: 22,
c: true
};
console.log(Object.values(object));
Year 2022 and JavaScript still does not have a sound way to work with hashes?
This issues a warning but works:
Object.prototype.keys = function() { return Object.keys(this) }
console.log("Keys of an object: ", { a:1, b:2 }.keys() )
// Keys of an object: Array [ "a", "b" ]
// WARN: Line 8:1: Object prototype is read only, properties should not be added no-extend-native
That said, Extending Built-in Objects is Controversial.
If you decide to use Underscore.js you better do
var foo = { 'alpha' : 'puffin', 'beta' : 'beagle' };
var keys = [];
_.each( foo, function( val, key ) {
keys.push(key);
});
console.log(keys);

Categories

Resources