I have JSON, which looks like this:
{ '-KiJz4D0pGYE35HPP-E4': { code: '211', lastname: 'Smith', firstname: 'John' } }
I do know that it will always look this way, ONLY one child in any case. How could I get value '211' stored under code key. Right now I have ugly code with foreach, it even works, but... Why would I use foreach at all if I know there is only one child?
Thanks a lot!
DEMO
var jsonObj = {
'-KiJz4D0pGYE35HPP-E4': {
code: '211',
lastname: 'Smith',
firstname: 'John'
}
};
var objKey = Object.keys(jsonObj); // return the object key
var innerObject = jsonObj[objKey]; // return the inner object
var code = innerObject.code; // return the code property value.
console.log(code);
USe Object.keys(obj)[0] to get the first key and then you can get the key code's value from it like
var obj = { '-KiJz4D0pGYE35HPP-E4': { code: '211', lastname: 'Smith', firstname: 'John' } }
console.log(obj[Object.keys(obj)[0]]['code']);
If
var data = { '-KiJz4D0pGYE35HPP-E4': { code: '211', lastname: 'Smith', firstname: 'John' } };
Then
data[Object.keys(data)[0]] will return your inner object
{ code: '211', lastname: 'Smith', firstname: 'John' }
So you easily get code value by data[Object.keys(data)[0]].code
Object.values({ '-KiJz4D0pGYE35HPP-E4': { code: '211', lastname: 'Smith', firstname: 'John' } })[0].code;
Simply get the first value of the outer Object...
Related
Let's suppose I have the following object:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
And that I want only the id and fullName.
I will do the following :
const { id, fullName } = user
Easy-peasy, right?
Now let's suppose that I want to do the destructuring based on the value of another variable called fields.
const fields = [ 'id', 'fullName' ]
Now my question is : How can I do destructuring based on an array of keys?
I shamelessly tried the following without success:
let {[{...fields}]} = user and let {[...fields]} = user. Is there any way that this could be done?
Thank you
It's not impossible to destructure with a dynamic key. To prevent the problem of creating dynamic variables (as Ginden mentioned) you need to provide aliases.
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName' ];
const object = {};
const {[fields[0]]: id, [fields[1]]: fullName} = user;
console.log(id); // 42
console.log(fullName); // { firstName: "John", lastName: "Doe" }
To get around the problem of having to define static aliases for dynamic values, you can assign to an object's dynamic properties. In this simple example, this is the same as reverting the whole destructuring, though :)
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName' ];
const object = {};
({[fields[0]]: object[fields[0]], [fields[1]]: object[fields[1]]} = user);
console.log(object.id); // 42
console.log(object.fullName); // { firstName: "John", lastName: "Doe" }
sources:
https://twitter.com/ydkjs/status/699845396084846592
https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch2.md#not-just-declarations
Paul Kögel's answer is great, but I wanted to give a simpler example for when you need only the value of a dynamic field but don't need to assign it to a dynamic key.
let obj = {x: 3, y: 6};
let dynamicField = 'x';
let {[dynamicField]: value} = obj;
console.log(value);
Short answer: it's impossible and it won't be possible.
Reasoning behind this: it would introduce new dynamically named variables into block scope, effectively being dynamic eval, thus disabling any performance optimization. Dynamic eval that can modify scope in fly was always regarded as extremely dangerous and was removed from ES5 strict mode.
Moreover, it would be a code smell - referencing undefined variables throws ReferenceError, so you would need more boilerplate code to safely handle such dynamic scope.
As discussed before, you can't destruct into dynamically named variables in JavaScript without using eval.
But you can get a subset of the object dynamically, using reduce function as follows:
const destruct = (obj, ...keys) =>
keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});
const object = {
color: 'red',
size: 'big',
amount: 10,
};
const subset1 = destruct(object, 'color');
const subset2 = destruct(object, 'color', 'amount', 'size');
console.log(subset1);
console.log(subset2);
You can't destruct without knowing the name of the keys or using an alias for named variables
// you know the name of the keys
const { id, fullName } = user;
// use an alias for named variables
const { [fields[0]]: id, [fields[1]]: fullName } = user;
A solution is to use Array.reduce() to create an object with the dynamic keys like this:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
const fields = [ 'id', 'fullName', 'age' ];
const obj = fields.reduce((acc, k) => ({ ...acc, ...(user.hasOwnProperty(k) && { [k]: user[k] }) }), {});
for(let k in obj) {
console.log(k, obj[k]);
}
I believe that the above answers are intellectual and valid because all are given by pro developers. :). But, I have found a small and effective solution to destructure any objects dynamically. you can destructure them in two ways. But both ways are has done the same action.
Ex:
const user = {
id: 42,
displayName: "jdoe",
fullName: {
firstName: "John",
lastName: "Doe"
}
};
using "Object.key", "forEach" and "window" object.
Object.keys(user).forEach(l=>window[l]=user[l]);
Simply using Object. assign method.
Object.assign(window, user)
Output:
console.log(id, displayName, fullName)
// 42 jdoe {firstName: "John", lastName: "Doe"}
Anyway, I am a newbie in JS. So, don't take it as an offense if you found any misleading info in my answer.
what could i do to assign the value of firstName's property to lastName's?
const user = {
firstName: "Someone",
lastName: this.firstName,
};
console.log(user.lastName);
// outputs undefined
Using a getter:
const user = {
firstName: "Someone",
get lastName() { return this.firstName; }
};
console.log(user.lastName);
Following code outputs {name: "Bob", surname: "Smith"} and it works fine. I want to know can I make it shorter.
((person = { name: 'Bob', surname: 'Smith', age: 22, }) => {
const {
name, // (a) create variable from deconstructing
surname,
} = person;
return {
name, // (b) reuse variable as new object parameter name (and value)
surname
}
})();
Can I somehow merge object deconstruction to variables (a) with returning a new object with Object Property Value shorthand (b)?
I use here shorthand but then its purpose is defeated by the need to manually re-use parameters. I want to mention the name or surname word in my function once not twice...
Destructure person in the function's declaration:
const result = (({ name, surname } = { name: 'Bob', surname: 'Smith', age: 22, }) => ({
name, // (b) reuse variable as new object parameter name (and value)
surname
}))();
console.log(result);
You can not mention it at all
((person = { name: 'Bob', surname: 'Smith', age: 22, }) => {
const {age,...ans} = person;
return ans
})()
I am trying to compare two objects and construct a third one if the value stored in a property of one is different than the other. If not I am storing an empty string. The way am doing it in my opinion is super inefficient and non sustainable. This wont work if the keys change or their number increases. I have to be able to do this programmatically with pure JS, no jQuery:
var staleProfile = {
firstName: 'john',
lastName: 'smith',
email: 'js#gmail.com'
}
var CurrentCustomer = {};
CurrentCustomer.profile = {
firstName: 'paul',
lastName: 'smith',
email: 'js#yahoo.com'
}
var returnObj = {};
returnObj.firstName = staleProfile.firstName != CurrentCustomer.profile.firstName ? CurrentCustomer.profile.firstName : ''
returnObj.lastName = staleProfile.lastName != CurrentCustomer.profile.lastName ? CurrentCustomer.profile.lastName : ''
returnObj.email = staleProfile.email != CurrentCustomer.profile.email ? CurrentCustomer.profile.email : ''
This searches for all the object keys in the CurrentCustomer.profile and checks for differences to the staleProfile. It adds keys to the diff, that only exist in object1 but not in object0, but doesn't take care of keys that are removed from object0to object1.
var staleProfile = {
firstName: 'john',
lastName: 'smith',
email: 'js#gmail.com',
key0: 'value0'
}
var CurrentCustomer = {};
CurrentCustomer.profile = {
firstName: 'paul',
lastName: 'smith',
email: 'js#yahoo.com',
key1: 'value1'
}
function createDiffObject(object0, object1) {
var diff = {};
Object.keys(object1).forEach(function(key) {
if (!object0.hasOwnProperty(key) || object0[key] != object1[key]) {
diff[key] = object1[key];
} else {
diff[key] = '';
}
});
return diff;
}
console.log(createDiffObject(staleProfile, CurrentCustomer.profile));
// output:
/*
{ firstName: 'paul',
lastName: '',
email: 'js#yahoo.com',
key1: 'value1' }
*/
An option would be to get all the keys present in your object using Object.keys(staleProfile).
After this you can loop through the keys and compare values. See an example down below.
var keys = Object.keys(staleProfile),
i, j,
comparedObject = {},
key,
CurrentCustomer = {
a:a,
b:b,
c:c
};
for (i = 0, j = keys.length; i < j; i++) {
key = keys[i];
if (staleProfile[key] === CurrentCustomer[key]) {
comparedObject[key] === CurrentCustomer[key];
} else {
comparedObject[key] === '';
}
}
One way to do it is to make a small helper function to assign each property (or empty string):
// NOTE: staleProfile and CurrentCustomer are assumed to be in the scope above
// If this could be an issue, just pass them as parameters
function getProp(prop) {
let staleProp = staleProfile[prop];
let currProp = CurrentCustomer.profile[prop];
return staleProp != currProp ? currProp : '';
}
And then use it like:
let returnObj = {
firstName : getProp('firstName'),
lastName : getProp('lastName'),
email : getProp('email')
}
Running Example
var staleProfile = {
firstName: 'john',
lastName: 'smith',
email: 'js#gmail.com'
}
var CurrentCustomer = {};
CurrentCustomer.profile = {
firstName: 'paul',
lastName: 'smith',
email: 'js#yahoo.com'
}
function getProp(prop) {
let staleProp = staleProfile[prop];
let currProp = CurrentCustomer.profile[prop];
return staleProp != currProp ? currProp : '';
}
let returnObj = {
firstName: getProp('firstName'),
lastName: getProp('lastName'),
email: getProp('email')
}
console.log(returnObj);
The advantage of this helper function is that, in case you need to update your strategy for replacement of a missing value, you only have to do it in one place.
Furthermore, you could have an array of keys you would like to extract:
let keys = ['firstName', 'lastName', 'email'];
Or perhaps extract all using Object.keys:
let keys = Object.keys(staleProfile);
And then you can store the keys using the getProp function:
keys.forEach(k => {
returnObj[k] = getProp(k);
});
This would make adding/removing properties simply a matter of the current content the keys array. When you need to remove or add a property, you can either update the keys array in the first example, or update the staleProfile in the second example and let Object.keys return the values for you. Either way, with one small change you can add/remove properties.
Running example:
var staleProfile = {
firstName: 'john',
lastName: 'smith',
email: 'js#gmail.com'
}
var CurrentCustomer = {};
CurrentCustomer.profile = {
firstName: 'paul',
lastName: 'smith',
email: 'js#yahoo.com'
}
function getProp(prop) {
let staleProp = staleProfile[prop];
let currProp = CurrentCustomer.profile[prop];
return staleProp != currProp ? currProp : '';
}
let keys = Object.keys(staleProfile);
let returnObj = {};
keys.forEach(k => {
returnObj[k] = getProp(k);
});
console.log(returnObj);
Note: James Thorpe made a good observation in the comment.
what if one of the future properties you speak of could validly hold an empty string? In that case, you won't know if it's been updated to a an empty string or is unchanged. You may want to consider using null for unchanged items
I'm trying to find the value of an object using _.find in sails and somehow the returned result is undefined. I've checked with their documentation and it seems I am doing everything right. But it is still returning undefined. I badly need your help. Thank you.
var obj = [
{
profile: {
profileId: 12,
firstName: 'John',
lastName: 'Doe',
email: 'johndoe#mail.com',
}
},
{
profile: {
profile: 13,
firstName: 'Jane',
lastName: 'Doe',
email: 'janedoe#mail.com',
}
}
];
var fnd = _.find(obj, {email: 'janedoe#mail.com'})
console.log(fnd); //result is undefined
Your find line just has the wrong input, try this:
var fnd = _.find(obj,
{profile:
{email: 'janedoe#mail.com'}
});
Check out the fiddle.
You need to end with ; and if that doesn´t solve it I think you need to pass a function and then the condition, something like this
_.find(obj, function(profile) {
return profile.email == 'janedoe#mail.com';
});
I'm not an expert but the documentation says so.