Say I have the following json files:
const obj1 = {
en: {
user: {
name: "John"
}
},
language: "en"
}
const obj2 = {
ru: {
user: {
name: "Vladimir"
}
},
language: "ru"
}
To retrieve these objects with NODE I will use the following code:
let en_name = obj1.en.user.name; //returns John
let ru_name = obj2.ru.user.name; //returns Vladimir
Is it possible to use the object language, and call the user.name based on the language? maybe something like this, which doesn't work:
let lang = obj.language
let anyName = language.user.name;
UPDATE:
I want to access data.jvProfiles.ANY_LANGUAGE.title as shown in the figure:
console.log(data.preferredLanguage); //Returns "nl"
let title = data.jvProfiles.nl.title; //Ruturns "Database Marketeer"
console.log(data.jvProfiles.data[data.preferredLanguage]); //gives error
console.log(data.jvProfiles.data[data.preferredLanguage].title); //gives same error
TypeError: Cannot read property 'nl' of undefined
SOLUTION:
console.log(data.jvProfiles[data.preferredLanguage].title);
You can use square brackets notation to access an object property dynamically:
const obj = {
en: {
user: {
name: "John"
}
},
language: "en"
}
const name = obj[obj.language].user.name
console.log(name)
Related
I have some trouble in using spread operator.
when using spread operator, unexpected attribute exists in created object.
Can I filter only defined attribute or remove undefined attribute?
type test = { id: string }
const dump = { id: 'id', name: 'name' };
const testResult: test = { ...dump };
// wanted result { id: 'id' }
console.log('test', testResult); // test { id: 'id', name: 'name' }
I think the issue is not with respect to typescript alone here. Typescript is quite liberal in checking types. In the sense
interface IFoo {}
interface IBar {
name: string
}
// No error will be thrown
const foo: IFoo = { name: 'sam' };
const bar: IBar = { name: 'sam' };
// following line will throw error. As IBar expects the property name.
const justFoo: IBar = { greet: 'hello' };
Here foo can be used as a variable of one of types IFoo or IBar. Either will work. But it's not true in case of justFoo, it can only be IFoo.
This is how you should do it:
type test = { id: string }
const dump = { id: 'id', name: 'name' };
const testResult: test = {id:dump.id}
I am trying to generate an object via a for loop, the problem I am having is that the property name is not being generated instead it is just inserted as the variable name.
Here is an example:
for (let key in person) {
let obj = {key : person[key] };
console.log(obj);
}
If you run this it prints
{ key : "smith" }
The desired object would be
{ name : "smith" }
any ideas on how to achieve this? thank you in advanced.
What you want is :
const person = {
age: 18,
size: '1m74',
eyeColor: 'blue',
};
for (let key in person) {
const obj = {
[key] : person[key],
};
console.log(obj);
}
Look at here for explainations
Example with Array.forEach and Object.keys
const person = {
age: 18,
size: '1m74',
eyeColor: 'blue',
};
Object.keys(person).forEach((x) => {
const obj = {
[x]: person[x],
};
console.log(obj);
});
You can achieve using
for (let key in person) {
const obj = {};
obj[key] = person[key];
console.log(obj);
}
You can do this by :
obj = {name: person[key] }
So I will be constantly retrieving an object with the following format:
student: {
"student_id": "12345",
"location": "below",
},
]
},
]
Thank you and will accept answer and upvote!
Something like this should do the trick:
var students = [];
function addStudent(student) {
// Check if we already know about this student.
var existingRecord = students.find(function (s) {
return s.student_id === student.student_id;
});
var classInfo = {
class_number: student.class_number,
location: student.location
};
if (!existingRecord) {
// This is the first record for this student so we construct
// the complete record and add it.
students.push({
student_id: student.student_id,
classes: [classInfo]
});
return;
}
// Add to the existing student's classes.
existingRecord.classes.push(classInfo);
}
You would then invoke it as follows:
addStudent({
"student_id": "67890",
"class_number": "abcd",
"location": "below",
});
Runnable JSBin example available here.
More available on Array.prototype.find at MDN.
This problem can be solved using indexing by student_id. For example:
var sourceArray = [{...}, {...}, ...];
var result = {};
sourceArray.forEach(function(student){
var classInfo = {
class_number: student.class_number,
location : student.location
};
if(result[student.student_id]){
result[student.student_id].classes.push(classInfo);
} else {
result[student.student_id] = {
student_id : student.student_id,
classes : [classInfo]
}
}
});
// Strip keys: convert to plain array
var resultArray = [];
for (key in result) {
resultArray.push(result[key]);
}
You can use also result format that contains objects, indexed by student_id or plain array resultArray.
When working with nodejs, I like to use console.log to see what data is available in an object.
However, this doesn't work with inherited properties:
var Person = function () {};
Person.prototype.name = "anonymous";
var p = new Person();
console.log(['p', p]); // [ 'p', {} ]
// This doesn't even give me a hint that it's inherited from Person!
console.log(['typeof p', typeof p]); // [ 'typeof p', 'object' ]
console.log(['p.name', p.name]); // "anonymous"
Given an object, how can view all the properties I can access?
If your purpose is just for debugging, you can check the __proto__ object:
function Person() {};
Person.prototype.name = "abc";
Person.prototype.smallObj = {
name: "abc"
};
Person.prototype.deepObj = {
one: {
two: {
three: {
four: "4"
}
}
}
};
var p = new Person();
console.log(p);
// Person {}
console.log(p.__proto__);
/*
Person {
name: 'abc',
smallObj: { name: 'abc' },
deepObj: { one: { two: [Object] } }
}
*/
var util = require("util");
console.log(util.inspect(p.__proto__, {depth: null}));
/*
Person {
name: 'abc',
smallObj: { name: 'abc' },
deepObj: { one: { two: { three: { four: '4' } } } }
}
*/
On the last one, using util.inspect() with the depth option will allow you to look further into deeply nested objects.
You are assigning property to constructor function Person. It does not share properties with instances. You need to add property to Person's prototype:
Person.prototype.name = "anonymous";
To find out if your object inherited from Person you can do:
p instanceof Person; // true
You can print out all of an object's enumerable properties by performing the following:
for (var key in p) {
console.log(key);
}
Use Object.getOwnPropertyNames() to get all properties that belong to an object:
console.log(Object.getOwnPropertyNames(Person))
// [ 'length', 'name', 'arguments', 'caller', 'prototype' ]
console.log(Object.getOwnPropertyNames(Object))
// ['length','name','arguments','caller','prototype','keys','create', 'defineProperty','defineProperties','freeze','getPrototypeOf','setPrototypeOf','getOwnPropertyDescriptor','getOwnPropertyNames','is','isExtensible','isFrozen','isSealed','preventExtensions','seal','getOwnPropertySymbols','deliverChangeRecords','getNotifier','observe','unobserve','assign' ]
Also you can combine Object.getOwnPropertyNames() with walking up the prototype chain:
var getAllProperties = function (object) {
var properties = []
do {
Object.getOwnPropertyNames(object).forEach((prop) => {
if (!~properties.indexOf(prop)) {
properties.push(prop)
}
})
} while (object = Object.getPrototypeOf(object))
return properties
}
I want to add a new field with a variable name to an object in the DB : meaning, I don't know the name of the field, but it's held in a variable "newFieldName".
So what I want to do is basically this:
var newFieldName = "world";
db.bios.update(
{ _id: 3 },
{ $set: {
"hello."+newFieldName: "Amazing Grace"
}
}
)
After the update, I expect the object "hello" to have a field "world" with the value "Amazing Grace".
but this doesn't even compile, let alone work. How can I do it?
You can use an intermediary object:
var update = { $set : {} };
update.$set['hello.' + newFieldName] = 'Amazing Grace';
db.bios.update({ _id : 3 }, update, ...)
var some_object = Posts.findOne({...});
var new_value = 1337;
Posts.update(another_object._id,
{$set: {
[some_object.some_field]:new_value,
}
}
);
To answer #yossale & #robertklep, the inline version is in fact possible using an expression and the comma operator:
var newFieldName = "world", o;
db.bios.update(
{ _id: 3 },
{$set:(o = {}, o["hello."+newFieldName] = "Amazing Grace", o)}
)
Simple is that:
var newFieldName = "world";
db.bios.update(
{ _id: 3 },
{ $set: {
["hello."+newFieldName]: "Amazing Grace"
}
}
);
#Andy's answer solved my problem.