A dynamic property:
var obj = {
// Computed (dynamic) property names
[ 'prop_' + (() => 42)() ]: 42
};
This is of course very fancy. But where could someone use this without adding unnecessary complexity?
If you have a property name as a constant:
var obj = { [SOME_CONSTANT]: 42 };
One case where I wanted it was where property names for JSON were defined in generated files, based off Java classes.
// Generated
var SomeJsonBodyParams = {NAME: 'name', ID: 'id', ETA, 'estimatedTimeOfArrival'};
// Using it
sendAjax('some/url', {
[SomeJsonBodyParams.NAME] = userData.name,
...
});
We even had a method so we could kind of do it
function makeObj() {
var obj = {};
for (var i=0; i < arguments.length; i+=2) {
obj[i] = obj[i+i];
}
return obj;
}
sendAjax('some/url', makeObj(
SomeJsonBodyParams.NAME, userData.name,
...
));
You can use it in class and with Symbols:
class MyClass {
[Symbol.iterator]() {
// my iterator
}
}
Let's say you have:
var hi = 'hi';
var test = 'test';
var hello = 'hello';
Instead of:
var object = {};
object[hi] = 111;
object[test] = 222;
object[hello] = 333;
You could write it in a much shorter syntax:
var object = {
[hi]: 111,
[test]: 222,
[hello]: 333
}
E.g. it could be used when you want to use a, let's say, constant as a key in object.
const DATA_TYPE = {
PERSON: 'person',
COMPANY: 'company'
};
let cache = {
[DATA_TYPE.PERSON]: getPerson()
};
And later access:
cache[DATA_TYPE.PERSON]
Instead of DATA_TYPE.PERSON could be anything (including some real-time calculated values).
Related
I'm trying to create a dictionary object like so
var obj = { varName : varValue };
What I'm expecting is if varName='foo', the obj should be {'foo', 'some value' } however what I see is {varName, 'some value'} the value of variable is not being used but a variable name as a key. How do I make it so that varible value is used as key?
Try like this:
var obj = {};
obj[varName] = varValue;
You can't initialize objects with 'dynamic' keys in old Javascript. var obj = { varName : varValue }; is equivalent to var obj = { "varName" : varValue };. This is how Javascript interprets.
However new ECMAScript supports computed property names, and you can do:
var obj = { [varName]: varValue };
Starting with ECMAScript 2015, which has gotten better browser support in the last year(s), you can use the variable index notation:
const obj = { [varName] : varValue };
This is syntactically the same as
var obj = {};
obj[varName] = varValue;
You can also use expressions or Symbols as property key:
const contact = {
company: companyName,
};
const companiesWithContacts = {
[contact.company.toLowerCase()]: true
};
const myList = {
[Symbol.iterator]: createIteratorForList
};
function createIteratorForList() { ... }
I am attempting to dynamically create an object with name-value pairs using html input fields. This is what i have so far:
var taskComplete = {
newTask: function(arg) {
var fieldObj = {},
selector = arg,
inputFields = document.getElementsByClassName(selector);
for (var i=0;i<inputFields.length;i++) {
var attrValue = inputFields[i].getAttribute("name"),
value = inputFields[i].value,
newFieldObj = fieldObj[i] = {[attrValue]: value };
console.log(newFieldObj);
}
}
}
taskComplete.newTask('input');
The console log outputs:
Object {title: ""}
Object {description: ""}
Object {date: ""}
Question1:
How do i access these objects? they all share the same name eg. 'Object' so 'object.title' does not work.
Question2:
Is there a way to combine these objects into a single object?
eg.
var obj = {
title: "",
description: "",
date: "",
}
code example with html: codepen.io
Hope this make sense. Thank you for any and all assistance.
I will answer your questions in the reverse order, makes more sense, you will see.
Question2: Is there a way to combine these objects into a single object?
Yes, I am happy to inform you that you absolutely can. Where you do
newFieldObj = fieldObj[i] = {[attrValue]: value };
simply do
fieldObj[attrValue] = value;
What this does, is the following: On the fieldObj, which is a plain {} set a key named after the value of attrValue and pair that key with the value value
Question1: How do i access these objects? they all share the same name eg. 'Object' so 'object.title' does not work.
In order to be able to access these objects, your newTask method should be returning them. So, at the end of your newTask method, simply do return fieldObj; like so
var taskComplete = {
newTask: function(arg) {
var fieldObj = {},
selector = arg,
inputFields = document.getElementsByClassName(selector),
attrValue,
value;
for (var i=0;i<inputFields.length;i++) {
attrValue = inputFields[i].getAttribute("name");
value = inputFields[i].value;
fieldObj[attrValue] = value;
}
return fieldObj;
}
}
and then store the returned value to a new variable like so:
var aFancyName = taskComplete.newTask('input');
Here's the modified pen: http://codepen.io/anon/pen/XdjKQJ
Not super clear on what you are trying to do here.
Instead of creating a new object for each iteration of your loop, why not just assign those properties to the fieldObj you already have?
Then you can just return that object and do whatever you want with it in the calling code:
'use strict';
// ** TASK OBJECT ** //
var taskComplete = {
newTask: function(selector) {
var fieldObj = {},
inputFields = document.getElementsByClassName(selector);
for (var i = 0; i < inputFields.length; i++) {
var attrKey = inputFields[i].getAttribute("name"),
value = inputFields[i].value;
fieldObj[attrKey] = value;
}
return fieldObj;
}
}
var o = taskComplete.newTask('input');
console.dir(o);
http://codepen.io/anon/pen/reMLPB?editors=0010
Lets say I get this from an API:
var _persons = [
{
name: 'John'
},
{
name: 'Sarah'
}
];
Now I want to add a greeting function. I want to save memoryspace so I create a Person 'class' and add the function as a proto.
function Person(person){
this.person = person;
}
Person.prototype.greeting = function(){
return 'hello ' + this.person.name
};
I instantiate each person:
var persons = [];
function createPersons(people){
for(var i = 0;i<people.length;i++){
var person = new Person(people[i]);
persons.push(person);
}
};
createPersons(_persons);
Problem is this:
console.log(persons[0].name) //undefined
console.log(persons[0].person.name) //'John'
Is there anyway I can get the first console.log to work?
https://jsbin.com/zoqeyenopi/edit?js,console
To avoid the .person appearing in the object you need to copy each property of the source plain object directly into the Person object:
function Person(p) {
this.name = p.name;
...
}
[or use a loop if there's a large number of keys]
You've then got a mismatch between the named parameter and the variable you're iterating over in the createPersons function. Additionally it would make more sense to have that function return the list, not set an externally scoped variable:
function createPersons(people) {
return people.map(function(p) {
return new Person(p);
});
}
var persons = createPersons(_persons);
NB: the above uses Array.prototype.map which is the canonical function for generating a new array from a source array via a callback.
Loop over all the keys in your object argument and assign them to this
function Person(person){
for (var key in person) {
this[key] = person[key];
}
}
var persons = [];
function createPersons(people){
for(var i = 0;i<people.length;i++){
var person = new Person(people[i]);
persons.push(person);
}
};
createPersons(_persons);
Should be using people as a variable
You're creating a Person object that is given a variable person. You need to change the value you're getting by replacing
var person = new Person(people[i]);
with
var person = new Person(people[i]).person;
var _persons = [
{
name: 'John'
},
{
name: 'Sarah'
}
];
function Person(person){
this.person = person;
}
Person.prototype.greeting = function(){
return 'hello ' + this.person.name;
};
var persons = [];
function createPersons(people){
for(var i = 0;i<people.length;i++){
var person = new Person(people[i]).person;
persons.push(person);
}
};
createPersons(_persons);
console.log(persons[0].name); // logs 'John'
document.write('John');
myObject = {};
myObject.property1 = "123"
Typing myObject.property1 returns 123
mySecondObject = {};
mySecondObject.property1.value.type.price = "456"
returns TypeError: Cannot set property 'value1' of undefined because all or some parent keys haven't been defined yet, so you have to do something like:
mySecondObject = {};
mySecondObject.property1 = {};
mySecondObject.property1.value = {};
mySecondObject.property1.value.type = {};
mySecondObject.property1.value.type.price = "456"
Is there a method in JS that allows you to just declare an object with as many keys as you want and automatically creates all the parent keys? I couldn't find anything in Underscore.
There's no (standard) function for doing this.
An alternate initialiser is this:
var mySecondObject = { property1: { value: { type: { price : "456" } } } };
I'm building an object in javascript to store data dynamically.
Here is my code :
var id=0;
function(pName, pPrice) {
var name = pName;
var price = pPrice;
var myObj = {
id:{
'name':name,
'price':price
},
};
(id++); //
console.log(myObj.id.name); // Acessing specific data
}
I want my id field to be defined by the id variable value so it would create a new field each time my function is called. But I don't find any solution to concatenate both.
Thanks
You can create and access dynamicly named fields using the square bracket syntax:
var myObj = {};
myObj['id_'+id] = {
'name':name,
'price':price
}
Is this what you want ?
var myObj = {};
myObj[id] = {
'name':name,
'price':price
};
console.log(myObj[id]name); // Acessing specific data
You can use [] to define the dynamic property for particular object(myObj), something like
var myObj = {};
myObj[id] = {'nom':nom, 'prix':prix};
Example
function userDetail(id, nom, prix) {
var myObj = {};
myObj[id] = {'nom':nom, 'prix':prix};
return myObj;
}
var objA = userDetail('id1', 'sam', 2000);
var objB = userDetail('id2', 'ram', 12000);
var objC = userDetail('id3', 'honk', 22000);
console.log(objA.id1.nom); // prints sam
console.log(objB.id2.nom); // prints ram
console.log(objC.id3.prix);// prints 22000
[DEMO]