I have a object
let x = { "propName": "response" }
Is there a way we can change the key name for the object. I would like to pass an index for the propName like
{ "prop1Name": "response" }
Is there a way to do this, I know I cant do it like this but, I tried it with
var obj = { "prop"+i+"Name": "response" };
console.log(obj);
But, it failed ofcourse.
Is there a way to do it?
You can use the new ES6/Babel syntax of {[keyfromvariable]:"value"}, so, in your case...
var i = "1";
var obj = { ["prop"+i+"Name"]: "response" };
console.log(obj);
If you don't have ES6/Babel as an option, you can define the object first and then use []...
var i = "1";
var obj = {};
obj ["prop"+i+"Name"] = "response" ;
console.log(obj);
Related
So im editing some code and I would like to add another variable to an array. The code below works perfectly:
submit.addAttributeValue = function() {
var aValue = submit.status.newAttributeValue;
var aType = submit.status.selectedAttributeType;
console.log('adding value', aValue, aType)
if(aValue && aType ) {
submit.ProductMeta['attributes'][aType][aValue] = true;
};
};
I then add the variable aPrice to the function:
submit.addAttributeValue = function() {
var aValue = submit.status.newAttributeValue;
var aType = submit.status.selectedAttributeType;
var aPrice = submit.status.newAttributePrice;
console.log('adding value', aValue, aType, aPrice)
if(aValue && aType ) {
submit.ProductMeta['attributes'][aType][aValue][aPrice] = true;
};
};
I get the error:
Error: submit.ProductMeta.attributes[aType][aValue] is undefined
submit.addAttributeValue#http://dubdelivery.com/js/controllers-submit.js:369:13
ProductMeta is defined as: submit.ProductMeta = {};
Any advice on how I should approach this?
Thank You!
Your array is empty so you can't set a second level field before the first
If you have
var obj = {};
You have to set
obj.firstItem
before
obj.firstItem.secondItem
Here is an example
Look in the debugger or just console log "aType", "aValue", and "aPrice". I'm betting "aValue" is undefined.
If you're going to go about manipulating object properties this way, you have to make sure the variables that contain your property names actually have values.
(BTW, especially now with ES6 classes, you probably shouldn't be manipulating object property/values this way).
I'm trying to create a var with a couple of empty property's in it using JavaScript. In other languages (for sure in swift, but I'm sure in others too,) this is called a struct.
What I want it to look like is something like this:
myStruct {
value1 : String,
value2 : String
}
The closest I found to that is objects (JavaScript Objects), but with that you would have to add values (to my knowledge).
After, I need to add myStruct to an array. I hope this is clear. What is the most efficient way to achieve this?
Method 1:
The simplest of achieving this is to use new in combination with the Function constructor.
var myStruct = function(prop1,prop2){
this.prop1 = prop1;
this.prop2 = prop2;
}
var myStructObj = new myStruct();
var myStructObj2 = new myStruct("prop1","prop2");
var myArr = [];
myArr.push(myStructObj);
myArr.push(myStructObj2);
console.log(myArr);
An enhancement would be to add default params to the constructor and pass arguments while creation.
var myStruct = function(arg1, arg2){
var prop1 = arg1 || "defaultProp1Value";
var prop2 = arg2 || "defaultProp2Value";
this.prop1 = prop1;
this.prop2 = prop2;
}
var myStructObj1 = new myStruct();
//myStructObj1.prop1 is "defaultProp1Value"
//myStructObj1.prop2 is "defaultProp2Value"
var myStructObj2 = new myStruct("prop1");
//myStructObj2.prop1 is "prop1"
//myStructObj2.prop2 is "defaultProp2Value"
var myArr = [];
myArr.push(myStructObj1);
myArr.push(myStructObj2);
With ES6, you can do this, you can now add default parameters to the constructor.
//This only works in ES6
// Will cause errors on browsers which have not yet added support
// WIll work when used along with a transpiler like Babel
var myStruct = function(arg1 = "defaultProp1", arg2 = "defaultProp2"){
this.prop1 = arg1;
this.prop2 = arg2;
}
var myStructObj1 = new myStruct();
//myStructObj1.prop1 is "defaultProp1Value"
//myStructObj1.prop2 is "defaultProp2Value"
var myStructObj2 = new myStruct("prop1");
//myStructObj2.prop1 is "prop1"
//myStructObj2.prop2 is "defaultProp2Value"
var myArr = [];
myArr.push(myStructObj1);
myArr.push(myStructObj2);
console.log(myArr);
You can read more about it here
Method : 2
Using call method. With this approach you can add props on the fly. Whenever you want to add a couple of props to an object with either null values or default values you can use this approach.
var addPropsFunction = function(a,b){
this.prop1 = a;
this.prop2 = b;
}
var myObj1 = {};
var myObj2 = {};
addPropsFunction.call(myObj1);
addPropsFunction.call(myObj2,"val1","val2");
console.log(myObj1);
console.log(myObj2);
Method : 3
ES6 Classes
class myStruct{
constructor(prop1,prop2){
this.prop1 = prop1;
this.prop2 = prop2;
}
}
var myObj = new myStruct();
console.log(myObj);
Es6 Fiddle - http://www.es6fiddle.net/ifz3rjcc/
In all cases, changing properties is the same.
To change prop1's value, all you have to do is
myStructObj.prop1 = "my val";
null is a value which means "no value". Assigning null to your properties yields exactly what you need.
Well you could do
var myArray = [
{"value1":"Value1Here", "value2":"Value2Here"},
{"value1":"Value1Here", "value2":"Value2Here"},
{"value1":"Value1Here", "value2":"Value2Here"}
];
(these values can be null)
or you could declare your object as above
and do :
myArray.push(yourObject)
I think by now you know how to create a struct in JS.
Now, to initialize properties with empty values:
You have to use either null or undefined based on your requirement.
These links can help you in understanding what and how exactly you have to proceed.
null and undefined
Which one to use?
I'm trying to merge objects together, or add new objects to existing objects.
I've already got it working as for merge using jQuery, but it's the name of the property that wont work dynamically.
The parameter filters is an object, such as {test:123}.
When invoking filter({test:123});, I want the filter function to dynamically add objects to a global object. (and of course can't use push() since its not an array)
this.filter = function(filters) {
for (var key in filters) {
$.extend( settings.filter, {key:filters[key]} );
}
};
The problem is that "key" turns into "key" as the name of the property. When it should be "test" as the property name; I can not get the property name to be created dynamically.
The goal would be to allow the user to fire the function like this:
filter({test:123,test2:1321,test55:4})
and dynamically add objects to the global settings object without the user meddling with the object itself.
Your code does not work because key is not being interpreted as a variable when being directly set in the object.
$.extend( settings.filter, {key:filters[key]} );
Considering:
var keyName = "Test";
var badObj = { keyName: "Hello World" };
You would get undefined when calling newObj.Test because it is actually newObj.keyName.
In order to use a variable to create a property name, you need to use different syntax.
var keyName = "Test";
var newObj = {};
newObj[keyName] = "Hello World";
You could then reference and use newObj.Test to get "Hello World"
To fix the method you provided, you can adjust it to:
this.filter = function(filters) {
for (var key in filters) {
if (filters.hasOwnProperty(key)) {
var newObj = {};
newObj[key] = filters[key];
$.extend(settings.filter, newObj);
}
}
};
Keep in mind you can simplify this and just use the extend method. This would be better, unless you are looking to do your own filtering as the method name suggests.
this.filter = function(filters) {
$.extend(settings.filter, filters);
};
Demos
You should create temp obj before extend :
this.filter = function(filters) {
for (var key in filters) {
var obj = {};
obj[key] = filters[key];
$.extend( settings.filter, obj );
}
};
I have an object like:
var theObject = {
keyName1: { keyName2: value2, keyName3: value3, keyName4: value40 },
...,
keyName10: { keyName2: value6, keyName3: value7, keyName4: value8 }
}
I know I can reference value7 by theObject["keyName10"]["keyName3"] or theObject.keyName10.keyName3
but what I need is to set a variable to something like the search path and somehow pass it to theObject and get value7 directly.
Something like:
var path = keyName10.keyName3;
var myValue = theObject(path);
Objects can be even further into the object inception.
Right now I'm solving it by horrible looking nestled for-loops.
Is there a better way I missed?
I just try to add a solution for fun. I will definitively do not use it like this, but the idea might work for your situation. I also question the efficiency of this approach.
var theObject = {
keyName1: { keyName2: value2, keyName3: value3, keyName4: value40 },
...,
keyName10: { keyName2: value6, keyName3: value7, keyName4: value8 }
}
var path = 'keyName10/keyName3';
function getProp(theObject, path){
var parts = path.split("/"),
idx = parts[0],
newParts = parts.splice(0, 1),
newPath = newParts.join("/"),
obj = theObject[idx];
// add some validation and error handling in case or error on path
// or missing property on obj
// I do not like the line below, would need to find a better way to see
// if the function return something or it does some recursion
// need to figure the right condition to see if we are at des
if(parts.length == 1) {
return obj;
} else {
return getProp(obj, newPath);
}
}
Might help: How do I check if an object has a property in JavaScript?
Why not create a getter function...
var path = 'keyName10/keyName3'
function getTheThing(key){
var parts = key.split("/")
return theObject[parts[0]][parts[1]]
}
var myValue = getTheThing(path)
You could make it more general, by passing the object, and the key to the getter, allowing the path to be used to access different objects...
var path = 'keyName10/keyName3'
function getTheThing(key, obj){
var parts = key.split("/")
return obj[parts[0]][parts[1]]
}
var myValue = getTheThing(path,theObject)
Suppose I create a custom object/javascript "class" (airquotes) as follows:
// Constructor
function CustomObject(stringParam) {
var privateProperty = stringParam;
// Accessor
this.privilegedGetMethod = function() {
return privateProperty;
}
// Mutator
this.privilegedSetMethod = function(newStringParam) {
privateProperty = newStringParam;
}
}
Then I want to make a list of those custom objects where I can easily add or remove things from that list. I decide to use objects as a way to store the list of custom objects, so I can add custom objects to the list with
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = true;
myListOfCustomObjects[customObjectInstance2] = true;
myListOfCustomObjects[customObjectInstance3] = true;
and remove custom objects from the list with
delete myListOfCustomObjects[customObjectInstance1];
but if i try to iterate through the list with
for (i in myListOfCustomObjects) {
alert(i.privilegedGetMethod());
}
I would get an error in the FireBug console that says "i.privilegedGetMethod() is not a function". Is there a way to fix this problem or an idiom in javascript to do what I want? Sorry if this is a dumb question, but I'm new to javascript and have scoured the internet for solutions to my problem with no avail. Any help would be appreciated!
P.S. I realize that my example is super simplified, and I can just make the privateProperty public using this.property or something, but then i would still get undefined in the alert, and I would like to keep it encapsulated.
i won't be the original object as you were expecting:
for (i in myListOfCustomObjects) {
alert(typeof i); // "string"
}
This is because all keys in JavaScript are Strings. Any attempt to use another type as a key will first be serialized by toString().
If the result of toString() isn't somehow unique for each instance, they will all be the same key:
function MyClass() { }
var obj = {};
var k1 = new MyClass();
var k2 = new MyClass();
obj[k1] = {};
obj[k2] = {};
// only 1 "[object Object]" key was created, not 2 object keys
for (var key in obj) {
alert(key);
}
To make them unique, define a custom toString:
function CustomObject(stringParam) {
/* snip */
this.toString = function () {
return 'CustomObject ' + stringParam;
};
}
var obj = {};
var k1 = new CustomObject('key1');
var k2 = new CustomObject('key2');
obj[k1] = {};
obj[k2] = {};
// "CustomObject key1" then "CustomObject key2"
for (var key in obj) {
alert(key);
}
[Edit]
With a custom toString, you can set the object as the serialized key and the value to keep them organized and still continue to access them:
var customObjectInstance1 = new CustomObject('someString');
var customObjectInstance2 = new CustomObject('someOtherString');
var customObjectInstance3 = new CustomObject('yetAnotherString');
myListOfCustomObjects[customObjectInstance1] = customObjectInstance1;
myListOfCustomObjects[customObjectInstance2] = customObjectInstance2;
myListOfCustomObjects[customObjectInstance3] = customObjectInstance3;
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
The for iteration variable is just the index, not the object itself. So use:
for (i in myListOfCustomObjects) {
alert(myListOfCustomObjects[i].privilegedGetMethod());
}
and, in my opinion, if you use an Object as an array index / hash, it just would be converted to the string "Object", which ends up in a list with a single entry, because all the keys are the same ("Object").
myListOfCustomObjects =[
new CustomObject('someString'),
new CustomObject('someOtherString'),
new CustomObject('yetAnotherString')
]
you will get access to any element by index of array.