Setting values without instantiating a new object - javascript

What I am trying to do is be easily explain from the code.
How can I achieve in getting the correct result without creating a new object every time?
var optionsArr = new Array();
var labelObj = new Object();
labelObj.label = 'Pink';
labelObj.value = "Pink1";
optionsArr.push(labelObj);
labelObj.label = 'Green';
labelObj.value = "Green2";
optionsArr.push(labelObj);
console.log('optionsArr' + JSON.stringify(optionsArr));
expected result : {"label":"Pink","value":"Pink1"},{"label":"Green","value":"Green2"}
actual result : {"label":"Green","value":"Green2"},{"label":"Green","value":"Green2"}

var obj = [];
obj[0] = {"label" : "Pink","value" : "Pink1"};
obj[1] = {"label" : "Green","value" : "Green1"};
alert(JSON.stringify(obj));
OR the more proper way to handle an array:
var obj = [];
obj.push({
label: 'Green',
value: 'Green2'
});
obj.push({
label: 'Pink',
value: 'Pink1'
});
alert(JSON.stringify(obj));

In JavaScript objects are reference-type values, so there is no way to pass object value except for creating a new object, so you're limited to Object.assign option. The approach below would change desired properties and copy other ones:
var optionsArr = new Array();
var labelObj = new Object();
labelObj.label = 'Pink';
labelObj.value = "Pink1";
optionsArr.push(labelObj);
// Use Object.assign() to update only some of properties
optionsArr.push(Object.assign({}, labelObj, {
label: 'Green',
value: 'Green2'
}));
// Original object would remain unchaged
optionsArr.push(labelObj);
console.log('optionsArr' + JSON.stringify(optionsArr));

Related

How to check if Javascript Map has an object key

Looking at a couple of different docs, all I see is when the Map (ECMAScript6) key is a boolean, string, or integer. Is there a way we could use another customized Object (called with the new CustomObject(x,y) constructor call) to be added as a key?
I am able to add an object as a key, but unable to check if the Map has the said object.
var myMap = new Map();
myMap.set( new Tuple(1,1), "foo");
myMap.set('bar', "foo");
myMap.has(?);
myMap.has('bar'); // returns true
Is there a way around this?
var myMap = new Map();
myMap.set( new Tuple(1,1), "foo");
for(some conditions) {
var localData = new Tuple(1,1); //Use directly if exists in myMap?
map.has(localData) // returns false as this is a different Tuple object. But I need it to return true
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has
You just have to save the reference to the object:
var myMap = new Map();
var myKey = new Tuple(1,1);
myMap.set( myKey, "foo");
myMap.set('bar', "foo");
myMap.has(myKey); // returns true; myKey === myKey
myMap.has(new Tuple(1,1)); // returns false; new Tuple(1,1) !== myKey
myMap.has('bar'); // returns true; 'bar' === 'bar'
Edit: Here is how to use an object to achieve what you want, which is to compare objects by their values rather than by reference:
function Tuple (x, y) {
this.x = x;
this.y = y;
}
Tuple.prototype.toString = function () {
return 'Tuple [' + this.x + ',' + this.y + ']';
};
var myObject = {};
myObject[new Tuple(1, 1)] = 'foo';
myObject[new Tuple(1, 2)] = 'bar';
console.log(myObject[new Tuple(1, 1)]); // 'foo'
console.log(myObject[new Tuple(1, 2)]); // 'bar'
These operations will run in constant time on average, which is much faster than searching through a Map for a similar object key in linear time.
When you set an object to the map, you need to pass the same memory reference when checking if the map has it.
Example:
const map = new Map();
map.set(new Tuple(1,1));
map.has(new Tuple(1,1)) // False. You are checking a new object, not the same as the one you set.
const myObject = new Tuple(1,1);
map.set(myObject);
map.has(myObject) // True. You are checking the same object.
EDIT
If you really have to do this, you could do the following:
function checkSameObjKey(map, key) {
const keys = map.keys();
let anotherKey;
while(anotherKey = keys.next().value) {
// YOUR COMPARISON HERE
if (key.id == anotherKey.id) return true;
}
return false;
}
const map = new Map();
map.set({id: 1}, 1);
checkSameObjKey(map, {id: 1}); // True
checkSameObjKey(map, {id: 2}); // False

Setting up a object literal array to pass values to a server

I am passing a large number of variables to a http server. Instead of writing a long command prompt, I want to set up the variables as a object literal. If I set it up statically it works fine. But I want to populate the object in a loop.
This works:
var data= { T1: 123,
R1: 'L',
T2: 3434,
R2: 'R'};
$.post(url,data, get_outcome);
But I want to write a loop that does this, and I need to understand how I would populate the object literal with my variable names and values. (the example is just to demonstrate) If I try it this way it fails:
var data=[];
data.push({T1: 123});
data.push({T2: 3434});
data.push({R1: 'L'});
data.push({R2: 'R'});
$.post(url,data, get_outcome);
I have even tried this:
var data=[];
var a,val,name;
name={"T1","T2","R1","R2"};
val={"123","3434","L","R"};
for(a=0;a<4;a++){
data.push({name[a]:val[a]});
}
$.post(url,data,get_outcome);
The final function should work like this:
function Save(var values, var val){
var a,name;
var data=[];
for(a=0;a<values;a++){
name="T"+(a+1);
data.push({name: val[a]});
}
$.post(url,data,get_outcome);
}
What am I doing wrong ?
I implemented the solution suggested by Rajiv as follows:
function save(){
var data=[];
function dataPush(name, val) {
var obj = {};
obj[name] = val;
data.push(obj);
}
//eg hardcoded values
dataPush('T1',123);
dataPush('T2',3123);
dataPush('R1',"R");
dataPush('R2',"L");
// values stored in arrays elsewhere
for(a=2;a<max;a++){
temp="T"+(a+1);
dataPush(temp,T[a]);
temp="R"+(a+1);
dataPush(temp,R[a]);
}
$.post(url,data, get_outcome);
}
You are creating an array. Create like this
var data={};
data.T1 = 123;
data.T2 = 3434;
data.R1 = 'L';
data.R2 = 'R';
$.post(url,data,get_outcome);
And When using the array
var data={};
var a,val,name;
name={"T1","T2","R1","R2"};
val={"123","3434","L","R"};
for(a=0;a<4;a++){
data[name[a]] = val[a];
}
var data = {};
var name = ["T1", "T2", "R1", "R2"];
var val = [123, 3434, "L", "R"];
name.forEach(function(el, index){
data[el] = val[i];
});
Will produce
var data= { T1: 123,
R1: 'L',
T2: 3434,
R2: 'R'
};
var arry = [];
function dataPush(name, val) {
var obj = {};
obj[name] = val;
arry.push(obj);
}
KeyName =["T1","T2","R1","R2"];
KeyVal = ["123", "3434", "L", "R"];
for (var i = 0; i < KeyName.length; i++) {
dataPush(KeyName[i], KeyVal[i]);
}
console.log(arry);
After that used this array
All I understood from your question is that you need to create a object and send that to server. The object needs to have some properties that you wanna add dynamically, rather than statically.
If that's it, you can do so as :
var localData = [{key1: 'val1'},{key2: 'val2'},{key3: 'val3'}, {key4: 'val4', key5:'val5'}] // your data that you want to send
function createPayload(localData) {
var payload = {};
localData.forEach(function(o) {
for(var key in o) {
payload[key] = o[key];
}
});
return payload;
}
var objectToSend = createPayload(localData);
console.log(objectToSend);

Javascript multi-dimension array initialization

I'm looking for the best way to initialize multi-dimensional arrays in Javascript. I'm much more familiar with PHP where I'm not obliged to declare arrays or dimensions before feeding it with values.
Basically what I tried to do is create an array with the following format
catalogue[i]["name"]="a name";
catalogue[i]["description"]="a description";
...etc...
If I do the following:
var catalogue = new Array();
for (i=0; i<otherarray.length;i++)
{
catalogue[i]['name']=otherarray[i];
}
Catalogue is undefined, I also tried with catalogue[i].name but same issue. If I only assign a simple value like catalogue[i]=2, it works but that's not what I'm looking for. I couldn't find a working example of what I'm looking for.
Do I need to initialize every possible dimension of an array before being able to feed it with new values?
Thanks
Laurent
var catalogue = new Array();
for (i = 0; i < otherarray.length; i++) {
catalogue[i] = {};
catalogue[i]['name'] = otherarray[i];
}
Or
var catalogue = new Array();
for (i = 0; i < otherarray.length; i++) {
catalogue.push({"name":otherarray[i]});
}
Put this in your loop to create the object you want to store the values in:
catalogue[i] = {}; OR catalogue.push({});
Your code would be like this then:
var catalogue = new Array();
for (i=0; i<otherarray.length;i++)
{
catalogue[i] = {}; // initialization
catalogue[i]['name']=otherarray[i];
}
Note that you can initialize and assign a value in the same line:
var catalogue = new Array();
for (i=0; i<otherarray.length;i++)
{
catalogue[i] = {
name: otherarray[i],
otherKey: 'otherValue' // list all of your keys and values
};
}
If you want string keys in your array in Javascript you have to declare an Object. The catalogue variable itself is an array but each element inside that array is an object with the two keys "name" and "description". For example this code works :
var c = [1,2,3,4,5];
var n = ['one', 'two', 'three', 'four', 'five'];
var cat = [];
for (i = 0; i < c.length; i++)
{
cat[i] = {
name : n[i],
value: c[i]
};
}
now if you console.dir(cat); it outputs this result :
Array[5]
-> 0 : Object
name: "one"
value: 1
-> 1 : Object
name: "two"
value: 2
...

three.js: Access Scene Objects by Name or ID

I'm generating objects from an array which I've defined like this (It's not limited to these three):
var links = [['Linkedin','img/linkedin.png','-300','-230', '600'],
['Google+', 'img/google.png', '0', '-230', '600'],
['Twitter', 'img/twitter.png', '300', '-230', '600']];
Now it goes through the each loop to create and add the objects to the scene by Three.JS like this:
$.each(links, function(i, item) {
var thisItemTexture = THREE.ImageUtils.loadTexture(item[1]);
thisItemGeo = new THREE.CubeGeometry(60, 60, 60,1 ,1 , 1);
thisItemMat = new THREE.MeshBasicMaterial({map: thisItemTexture });
thisItem = new THREE.Mesh(thisItemGeo, thisItemMat);
scene.add(thisItem);
thisItem.position.x = item[2];
thisItem.position.y = item[3];
thisItem.position.z = item[4];
thisItem.castShadow = true;
thisItem.receiveShadow = true;
});
The question is: How can I access the objects that I've made in the each loop above?
You can do this:
myObject.name = "objectName";
...
var object = scene.getObjectByName( "objectName" );
or to recursively search the scene graph
var object = scene.getObjectByName( "objectName", true );
Alternatively, you can search by ID.
var object = scene.getObjectById( 4, true );
three.js r.61

Alter and Assign Object Without Side Effects

I currently have the following code:
var myArray = [];
var myElement = {
id: 0,
value: 0
}
myElement.id = 0;
myElement.value = 1;
myArray[0] = myElement;
myElement.id = 2;
myElement.value = 3;
myArray[1] = myElement;
The problem is that when I change the value of id and value for my second element, the values also change in the first element. Is there a way that I can keep adding new elements without it changing the value of the previously inserted values in the array?
Try this instead:
var myArray = [];
myArray.push({ id: 0, value: 1 });
myArray.push({ id: 2, value: 3 });
or will this not work for your situation?
This is a textbook case for a constructor function:
var myArray = [];
function myElement(id, value){
this.id = id
this.value = value
}
myArray[0] = new myElement(0,1)
myArray[1] = new myElement(2,3)
// or myArray.push(new myElement(1, 1))
You either need to keep creating new objects, or clone the existing one. See What is the most efficient way to deep clone an object in JavaScript? for how to clone.
That's because object values are passed by reference. You can clone the object like this:
var myArray = [];
var myElement = {
id: 0,
value: 0
}
myElement.id =0;
myElement.value=1;
myArray[0] = myElement;
var obj = {};
obj = clone(myElement);
obj.id = 2;
obj.value = 3;
myArray[1] = obj;
function clone(obj){
if(obj == null || typeof(obj) != 'object')
return obj;
var temp = new obj.constructor();
for(var key in obj)
temp[key] = clone(obj[key]);
return temp;
}
console.log(myArray[0]);
console.log(myArray[1]);
Result:
- id: 0
- value: 1
- id: 2
- value: 3
If you're using jQuery, you can use extend
myElement.id =0;
myElement.value=1;
myArray[0] = $.extend({}, myElement);
myElement.id = 2;
myElement.value = 3;
myArray[1] = $.extend({}, myElement);
Objects are passed by reference.. To create a new object, I follow this approach..
//Template code for object creation.
function myElement(id, value) {
this.id = id;
this.value = value;
}
var myArray = [];
//instantiate myEle
var myEle = new myElement(0, 0);
//store myEle
myArray[0] = myEle;
//Now create a new object & store it
myEle = new myElement(0, 1);
myArray[1] = myEle;
You will have the same object two times in your array, because object values are passed by reference. You have to create a new object like this
myElement.id = 244;
myElement.value = 3556;
myArray[0] = $.extend({}, myElement); //for shallow copy or
myArray[0] = $.extend(true, {}, myElement); // for deep copy
or
myArray.push({ id: 24, value: 246 });

Categories