Nested object properties with dynamic name [duplicate] - javascript

This question already has answers here:
Convert a JavaScript string in dot notation into an object reference
(34 answers)
Closed 6 years ago.
Context: I'm writing a Redux reducer (although this question is not Redux-specific) for my app's settings, which is a nested object. I want to modify the settings object using property names that are given dynamically.
Example:
const settings = {
service: {
username: 'TEST',
password: ''
}
}
// Normally this would be passed by Redux, but for the purposes of this exercise it's hardcoded
const settingKey = 'service.username';
console.log(settings[settingKey]); // undefined
console.log(eval(`settings.${settingKey}`)); // works, but bad
The only way I can think of accessing the subobject without using eval is using a regex to split the settingKey into its component parts:
const match = /(.+)\.(.+)/.exec(settingKey);
console.log(settings[match[1]][match[2]];
const settings = {
service: {
username: 'TEST',
password: ''
}
}
const settingKey = 'service.username';
const match = /(.+)\.(.+)/.exec(settingKey);
console.log(settings[match[1]][match[2]]);
This works, but
It's ugly
It doesn't work for more deeply nested objects
Is there a way of accessing a nested object's properties with a dynamic name without using regexes or eval?

You can do something like this,
var settings = {service: {username: 'TEST', password: ''}}
var key = "service.username";
function getValue(obj, keys){
keys.split(".").forEach(function(itm){
obj = obj[itm];
});
return obj;
}
getValue(settings, key); //"TEST"
Or you can do it simply using Array#reduce,
var settings = {service: {username: 'TEST', password: ''}}
var key = "service.username", result = key.split(".").reduce((a,b) => a[b], settings);
console.log(result); // "TEST"

Another option that doesn't use eval and works with nested properties.
var settings = {service: {username: 'TEST', password: ''}}
var key = "service.username";
console.log(Function('setting', 'return settings.' + key)(settings));

I think you just change one bit:
const settings = {
service: {
username: 'TEST',
password: ''
}
}
console.log(settings['service'].username);

Related

Object.assign can`t find declared variable [duplicate]

This question already has answers here:
Add a property to a JavaScript object using a variable as the name? [duplicate]
(14 answers)
Closed 2 years ago.
I feel like my problem is really easy to solve, but I cannot see it. I have simple thing to do, get myObject from another function and store this in my storage object. For this task I created storageHandler function. Everything works fine, but Object.assign is not reaching my 'ID' that I declared in this function earlier. This is weird because I don't know how to tell my function that 'ID' is variable, not a string. I just expect it to be {1212313: {...}} but instead it gives me {ID: {...}}.
Someone have any idea how to fix it?
let storage = {}
const myObject = {
ID: '1223424525221',
name: 'Thomas',
mail: 'example#example.com'
}
storageHandler = data => {
const {ID} = data;
Object.assign(storage, {ID: data})
console.log(storage)
}
storageHandler(myObject)
That's because in javascript this
a = { b: 1 };
is the same as
a = { "b": 1 };
You should change the Object.assign() for something like this
storage[ID] = data;
You should use the value of ID as key of object using [].
Object.assign(storage, {[ID]: data})
You are using string as a property name. Use computed property name like [ID] instead of ID. Computed property allows you to have an expression be computed as a property name on an object.
let storage = {};
const myObject = {
ID: '1223424525221',
name: 'Thomas',
mail: 'example#example.com',
};
storageHandler = (data) => {
const { ID } = data;
Object.assign(storage, { [ID]: data });
console.log(storage);
};
storageHandler(myObject);

Any way to make "const {user, userId} = this.state" work if user references username and userId references id [duplicate]

This question already has an answer here:
ES6/ES2015 object destructuring and changing target variable
(1 answer)
Closed 2 years ago.
for example
state = {
"username": "abc",
"id": "1",
}
const {username, id} = this.state
the above code would work and get the values
is there a way to make it so below would also work
const {user, userId} = this.state
That is, get the same values as username, id but with different names. Any way to tell javascript that user means username and userId means id?
You can do like this if you just want to use different names:
const {username: user, id: userId} = this.state
Yes you can do it like this:
const {username: user, id: userId} = this.state
Great docs here https://javascript.info/destructuring-assignment
Assigning to new variable names:
const o = {p: 42, q: true};
const {p: foo, q: bar} = o;
console.log(foo); // 42
console.log(bar); // true
More information:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

How to check if an object has keys that are in an array?

I have an array of strings and I want to check if the object has all properties that are in this array.
I could do a for loop and use .hasOwnProperty() but I want a better and smaller way to do it. I tried things like .includes , var v in obj, passing an array to .hasOwnProperty but nothing seems to work.
const obj = {Password: '123456', Username: 'MeMyselfAndI'}
const checkFields= ['Method', 'Password', 'Username']
return checkIfObjectHaveKeysOfArray(obj, checkFields) // should return false because object doesn't have property 'Method'
Is there a way to do that without using a for loop? If yes, how?
I could do a for loop and use .hasOwnProperty() but I wan't a better and smaller way to do it
Loops aren't that big. :-) But you could use every with an arrow function:
return checkFields.every(key => obj.hasOwnProperty(key));
Live Example:
const obj = {Password: '123456', Username: 'MeMyselfAndI'}
const checkFields= ['Method', 'Password', 'Username']
const result = checkFields.every(key => obj.hasOwnProperty(key));
console.log(result); // false
You could use Object.hasOwnProperty and check every key.
const
object = { Password: '123456', Username: 'MeMyselfAndI' },
checkFields = ['Method', 'Password', 'Username'],
hasAllKeys = checkFields.every({}.hasOwnProperty.bind(object));
console.log(hasAllKeys);

How to create JSON data in JS [duplicate]

This question already has answers here:
How to declare nested objects in JavaScript?
(2 answers)
Closed 7 years ago.
I would like to create a json object such as this that I can send to the server:
{
"email": "some#gmail.com",
"profile": {
"token": "test"
}
}
I can create the JSON but don't know how to create one that has multiple objects like the one above. This is what I've done so far
(In Console)
> var dataModel = { email: "somemail#gmail.com", token: "sometoken"}
> undefined
> dataModel
> Object {email: "somemail#gmail.com", token: "sometoken"}
The token needs to be inside profile
Most modern browsers have JSON.stringify(yourData) and JSON.parse(jsonData);
Just create your object as a plain JavaScript object:
var object = {
email: "some#gmail.com",
profile: {
token: "test"
}
}
Then convert it to JSON:
var json = JSON.stringify(object);
var dataModel = {
email: "somemail#gmail.com",
profile: {
token: "sometoken"
}
};
var dataModelJSON = JSON.stringify(dataModel);
Supported by main browsers: http://caniuse.com/#search=JSON.stringify
try:
var dataModel = { email: "somemail#gmail.com"};
dataModel.profile = {token : "test"}

Check if property is not undefined

I'm building a node+express app and I'm filling an object with JSON that's submitted from a form in the frontend. This works, unless I leave a field empty in the form so that e.g. req.body.address.street is empty/undefined.
This will result in the error:
TypeError: Cannot read property 'street' of undefined
var b = new Business({
name: req.body.name,
phone: req.body.phone,
address: {
street: req.body.address.street,
postalCode: req.body.address.postalCode,
city: req.body.address.city
},
owner: {
email: req.body.owner.email,
password: req.body.owner.password
}
});
My question is how I can best prevent my app from crashing when values are empty. I would like to avoid manually checking each and every property in my app against undefined.
I'm wondering what the best practice is for this common issue.
I don't know if you use jQuery in your project, but if you do, you can create a mask:
// creating your object mask
var req = {
body: {
name: '',
phone: '',
address: {
street: '',
postalCode: '',
city: ''
},
owner: {
email: '',
password: ''
}
}
}
And then, you simply use the jQuery "extend" method (req2 is your submmited object):
$.extend(true, req, req2);
I've create this fiddle for you!
-
Update
Nothing related to your question, but I've just noticed that you're passing an object with a similar structure of req.body to the Business class. However, there is no need to copy property by property manually - you can make, for example, a simple copy of req.body to pass as parameter:
var b = new Business($.extend({}, req.body));
or
var b = new Business(JSON.parse(JSON.stringify(req.body)));
You can't, really. You have two options;
Use a try/ catch:
try {
var b = new Business({
//
});
} catch (e) {
// Something wasn't provided.
}
... or you can define a helper function:
function get(path, obj) {
path = path.split('.');
path.shift(); // Remove "req".
while (path.length && obj.hasOwnProperty(path[0])) {
obj = obj[path.shift()];
}
return !path.length ? obj : null;
}
... you could then replace your use of req.body.address.street etc. with get('req.body.address.street', req).
See a demo here; http://jsfiddle.net/W8YaB/

Categories