This question already has answers here:
What is the most efficient way to deep clone an object in JavaScript?
(67 answers)
Closed 8 years ago.
here is my problem, reported in a way much more simplified
this is the json (look at the json here if you want)
{"resource":[{"id":"1408694994","obj":[{"id":"1","action":[{"name":"ON","id":"301"},{"name":"OFF","id":"302"}]},{"id":"2","action":[{"name":"ON","id":"303"},{"name":"OFF","id":"304"}]}]},{"id":"1408694995","obj":[{"id":"3","action":[{"name":"ON","id":"305"},{"name":"OFF","id":"306"}]},{"id":"4","action":[{"name":"ON","id":"307"},{"name":"OFF","id":"308"}]}]}]}
Given an id (in this case we say id = 3), I must save the item with that ID.
And i save in a new object (newobj) the object with that ID, but changing the array ACTION in an OBJ with the only action ON
Example
<script>
var tt = '{"resource":[{"id":"1408694994","obj":[{"id":"1","action":[{"name":"ON","id":"301"},{"name":"OFF","id":"302"}]},{"id":"2","action":[{"name":"ON","id":"303"},{"name":"OFF","id":"304"}]}]},{"id":"1408694995","obj":[{"id":"3","action":[{"name":"ON","id":"305"},{"name":"OFF","id":"306"}]},{"id":"4","action":[{"name":"ON","id":"307"},{"name":"OFF","id":"308"}]}]}]}';
var myjson = JSON.parse(tt);
var search = 3;
console.log(myjson.resource[1].obj[0]);
for(var i = 0 ; i < myjson.resource.length; i++){
for(j = 0 ; j < myjson.resource[i].obj.length; j++){
if(parseInt(myjson.resource[i].obj[j].id) == search){
var newobj = myjson.resource[i].obj[j];
var obj_action = newobj.action;
for(var k = 0 ; k < obj_action.length ; k++){
if(obj_action[k].name == "ON"){
newobj.action = obj_action[k];
}
}
}
}
}
console.log(myjson.resource[1].obj[0]);
</script>
I can easily save in the variable newobj the object that i want. But why the initial json is changed ???
UPDATE
ok, I understand that it is clearly problem of how I save the obj in newobj variable. i dont' save the object, but only the reference at the object in json . how can I save it in the variable newobj ? (not by reference?)
One way of decoupling object references is to serialize and deserialize as JSON. In this case, you could do something like this:
var newobj = JSON.parse(JSON.stringify(myjson.resource[i].obj[j]));
Note that this won't work every time. Complex objects with functions or prototypes won't be saved, for example.
It also comes with a slight performance hit.
Related
I have an array of objects:
var Props = [booleanPoint, buttonPoint, checkboxPoint, datePoint, dialPoint, gaugePoint,
groupboxPoint, htmlPoint, imagePoint, livetextPoint, livetrendsPoint, permissionsPoint,
rangePoint, selectPoint, spectrumPoint];
Console log shows:
Edited:
I want to extract the properties inside each object. How do I do it?
To be clear I just want the first property in the array, so that I can do Props.booleanPoint, Props.buttonPoint etc.
You question is not very clear, but I guess you're trying to extract the first (and only) property from each object in the list, whose name you don't know.
If yes, consider this:
extracted = Props.map(function(obj) {
for(var p in obj)
return obj[p];
});
If you want to combine all properties into one big object, try this:
allProps = Object.assign.apply(null, Props)
I'm not sure exactly what result you're after, but the best solution is probably either a forEach or a map.
var properties = {};
Props.forEach(function(object) {
// update properties somehow based on object
});
or
var properties = Props.map(function(object) {
return [some property of object];
});
The first just runs some code on each entry in the array; the second returns a new array with the results of that code.
Otherwise, the classic for loop works too:
var properties = {};
for (var i = 0; i < Props.length; i++ {
// update properties somehow based on Props[i]
}
Please see attached screenshot. See pendingApp property of Object. when I am debugging in eclipse then pendingApp show array of object, Which is correct! But when I am JSON.stringify(object) then showing me empty Array.
Please let me know reason of this behavior. I think I am not aware with any Java-Script thought/concept ?? :P :)
When I will save this Object into DB then blank array of pendingApp will be stored !!
var pending_app = [];
var new_record = {"pendingApp" : [], "installedApp" :[] };
....SOME CODE+conditions HERE....
pending_app[appId] = {'action' : action };
new_record.pendingApp = pending_app;
// create app-config data
return app_model.create(new_record); //will return promise object
It's not a weird behaviour but a common mistake of using an Array to store key-value data.
Short Answer : Use a literal Object to store these data
While you can add properties on every objects in Javascript, you cannot iterate over them with the default array mechanisms
for (var i = 0; i < array.length; i++){}
array.forEach();
Simple demonstration :
var array = [];
array["anId"] = 1;
array.length; // 0
array[4294967295] = 1; // Indice >= unsigned 32-bit Max Value
array.length; // 0
array[4294967295]; // 1
So JSON.stringify with the ECMAScript 5 Specification will use the Array mechanism to iterate over all items and will find nothing.
Unlike Objects that you can list properties with
Object.keys(array); // ["anId"]
I'm trying to create an object that contains an array of objects. I'm using a jquery selector to determine the number of objects I want in the array. I'm having some issue here because when I enter the for loop Firefox says that "this.obj is undefined" I tried both the the this.obj = new Array() syntax as well as the this.obj[ ]; syntax.
function Base() {
this.n = document.querySelectorAll('transform').length /3;
this.obj = new Array(n); //array declaration
for (var i = 0; i < this.n; i++) {
this.obj[i] = new x3dSphere("b"+i);
}
}
I've only seen examples of arrays within objects that are declared like this.obj = [1,2,2,4] or the in the JSON form obj: [1,2,3,4]. I'm sure this is something really easy to do but I can't seem to find an example anywhere.
The following worked for me:
function Base() {
this.n = 5;
this.obj = [];
for (var i = 0; i < this.n; i++) {
this.obj.push(new Test());
}
}
Where Test was:
var Test = function () {};
It seems like the real problem is that it never created this.obj because n was undefined. If you want to declare the array how you did before, try new Array(this.n).
EDIT
Would new Array(this.n) be faster than the this.obj=[] syntax since it's pre-allocated?
Interestingly enough, the answer is no.
Additionally, the accepted answer on this question has a great discussion of lots of other aspects of JavaScript array performance: What is the performance of Objects/Arrays in JavaScript? (specifically for Google V8)
I've updated my answer to use Array.push() because it is apparently much, much faster than doing Array[i] = new Obj() (shout out to Jason, who used it in his original answer).
You can declare an array with
this.obj = [];
And then push objects into the array in a loop
for (var i =0; i < n; i ++) {
this.obj.push(new x3dSphere ());
}
I get unexpected behavior when trying to load a hash using objects as keys; ie, when retrieving my data later the hash always refers to the last key used. I would expect this to be due to the behavior of closures, however, I thought that I have done what would be necessary to prevent this:
var hash = {};
var arry = [];
var list = [{val:"a"},{val:"b"},{val:"c"}];
var len = list.length;
dump("load : \n");
for (var i=0;i<len;i++) {
let pos = i;
let obj = list[pos];
hash[obj] = obj.val;
arry.push(obj);
dump(" "+obj.val+" "+hash[obj]+"\n");
}
dump("retrieve : \n");
for (var i=0;i<len;i++) {
let pos = i;
let obj = list[pos];
dump(" "+obj.val+" "+arry[pos].val+" "+hash[obj]+"\n");
}
output is:
load :
a a
b b
c c
retrieve :
a a c
b b c
c c c
I have purposely gone overboard in trying to prevent this by raising the scope of the iteration objects using let, still I am apparently missing something. I would like to understand the reason behind this, and how to prevent it using Javascript.
Object keys in JavaScript can only be strings. This means that if you pass something that is not a string, it gets converted to a string. Since you're using objects that don't "override" Object.toString, they'll all have the same string representation (it's "[object Object]"), which is why the hash always refers to the last key used.
More here: Strange equality issue with Javascript object properties
To extend #Matt Ball answer:
You can use JSON.stringify to string objects.
var a = {};
a.b = 1;
JSON.stringify(a);
// '{"b": 1}'
Note: You can't stringify circular objects:
var a = {};
a.a = a;
JSON.stringify(a);
// TypeError: Converting circular structure to JSON
i have created an array,
var myBuildingName=['A1','A2','A3','A4'];
where A1,A2,A3 and A4 are the names obtained through user input.
i now want to create arrays that have names A1,A2,A3 and A4.
i have tried using
for(var i=0;i<myBuildingName.length;i++)
{
var myBuildingName[i]=[];
}
but it does not work...
please help.
You create a master parent object and use the array values as keys into the object where you can store an array for each.
var myBuildingName=['A1','A2','A3','A4'];
var master = {};
for (var i = 0; i < myBuildingName.length; i++) {
master[myBuildingName[i]] = [];
}
Then, you can access the data like:
var a1Array = master['A1'];
or
var firstA1Item = master['A1'][0];
If you actually wanto create variables with those names (which I won't recommend), you'd have to eval() them. So:
for(var i=0;i<myBuildingName.length;i++)
{
eval("var " + myBuildingName[i] + " = [] "); // This creates Array variables called A1, A2 etc.
}
Again, the above method is NOT recommended. You should assign the names as keys to an object literal, like:
var myStuff = {};
for(var i=0;i<myBuildingName.length;i++)
{
var myStuff[myBuildingName[i]] = [];
}
You can't access the local variable object (except in global code), so you can't add properties other than by variable declaration. For global code in the global context you could do:
var global = this;
for ( ...) {
global[myBuildingName[i]] = []
}
but you can't do that for function code in function context. See jfriend00's answer.
Here's a demo
var myBuildingName = ['A1', 'A2', 'A3', 'A4'];
function arrayFromNames(arr) {
var store = {}; //storage for the arrays
for (var i = 0; i < arr.length; i++) { //for each in the passed names
store[arr[i]] = []; //add to the storage an array with the corresponding name
}
return store; //return the storage
}
var nameArrays = arrayFromNames(myBuildingName); //build using your array
console.log(nameArrays);
//you now have:
//nameArrays.A1, nameArrays.A2,...
//or
//nameArrays['A1'], nameArrays['A2'],...
You have received a lot of great answers, if one of them serves your need, you should accept that answer. The fact that this is still open makes us think no-one has quite answered your question the way you had hoped.
If that is the case, I can only assume that you wanted to use those variables in a global scope.
var myBuildingName=['A1','A2','A3','A4'];
for (var i = 0; i < myBuildingName.length; i++) {
window[myBuildingName[i]] = [];
}
Now you can access your variables 'normally'.
A1.push('test');
Note: this is horrible practice, since you should never pollute the global space.