iwato Posted September 21, 2018 Share Posted September 21, 2018 (edited) BACKGROUND: I have created a function whose job is to recreate an array of objects whose objects contain a vastly reduced, pre-selected number of property-value pairs. Although my function recreates the desired properties, the values are returned undefined. THE CODE: var propertyArr = ['serverDate', 'visitorId', 'visitCount']; function getEntries (propertyArr, inputArr) { var entryArr = []; var entry = {}; $.each(inputArr, function(key, object) { for(var property in propertyArr) { var prop = propertyArr[property]; entry[prop] = object.prop; } entryArr.push(entry); }); return entryArr; } console.log('entryArr', getEntries(propertyArr, jsonData)); THE RESULT SET entryArr Array [ Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, 90 more… ] where a typical object appears as follows: Object: serverDate: undefined visitorId: undefined visitCount: undefined QUESTION: Where have I gone wrong, and what can I do to fix my error. Roddy Edited September 21, 2018 by iwato Code upgrade Link to comment Share on other sites More sharing options...
iwato Posted September 21, 2018 Author Share Posted September 21, 2018 (edited) Almost there, a portion of the problem has been resolved with the following alteration. entry[prop] = object[prop]; I have just learned that there is a reason for having two ways to call the values of object properties. Unfortunately, the iteration is not working properly, for every object returns the same key-value pairs -- those of the last object only. Woe unto me! Roddy Edited September 21, 2018 by iwato Link to comment Share on other sites More sharing options...
Ingolme Posted September 21, 2018 Share Posted September 21, 2018 The variable entry should be declared inside the .each() callback. 1 Link to comment Share on other sites More sharing options...
iwato Posted September 22, 2018 Author Share Posted September 22, 2018 That was it! Thank you, Ingolme. Now, if I could only understand it. There appears to be much more involved in this case than a simple matter of scope. How is it that I am able to recreate the same variable over and over again? Roddy var entry = {}: Link to comment Share on other sites More sharing options...
Ingolme Posted September 22, 2018 Share Posted September 22, 2018 The problem before is that you created only one object and on each iteration you changed the properties of that object and added a new pointer to it from the array. What you really need to do is to create a new object on each iteration. You can recreate the variable every time because it is inside its own function. Another option would be to declare the object outside and initialize it inside the loop: var entry; // Reserve memory for storing objects $.each(inputArr, function(key, object) { entry = {}; // Create a new instance of an object and place it in the reserved memory for(var property in propertyArr) { var prop = propertyArr[property]; entry[prop] = object.prop; // Set the properties of the object } entryArr.push(entry); // Add a pointer to the new object at the end of the array }); return entryArr; They both do the same thing but for different reasons. 1 Link to comment Share on other sites More sharing options...
iwato Posted September 22, 2018 Author Share Posted September 22, 2018 You appear to be saying that each iteration of the same function is a different function. Have I understood correctly? Roddy Link to comment Share on other sites More sharing options...
Ingolme Posted September 22, 2018 Share Posted September 22, 2018 No, it is the same function. Every time the program enters a function, new memory is allocated for it. When the program leaves the function all of the memory used by the function is freed unless there are pointers to it from another part of the program, such as the array that was declared outside. 1 Link to comment Share on other sites More sharing options...
iwato Posted September 22, 2018 Author Share Posted September 22, 2018 OK. I think I have it. Using your last example as my heuristic template, then 1) Create a space in memory called entry. var entry; 2) Fill that space with a new object called entry with each iteration of the $.each() function. entry = {}; // Create a new instance of an object and place it in the reserved memory for(var property in propertyArr) { var prop = propertyArr[property]; entry[prop] = object.prop; // Set the properties of the object } 3) From that storage space retrieve the current value of entry (the just created object) and add it to a predefined array called entryArr. entryArr.push(entry); Is this correct? Roddy Link to comment Share on other sites More sharing options...
Ingolme Posted September 22, 2018 Share Posted September 22, 2018 The last example I wrote is a bit more complicated at the processor level, I was just showing an alternative way to do things. It is probably best to have the declaration inside the each() callback as I said initially. You're mostly correct, with a couple of differences due to the way scope and references work. 2) If the space does not have an object yet, it behaves as you said and puts the object in that space. If there was already an object in that space, the variable entry is changed to point to a new space in memory and the new object is placed there instead. The old object remains exactly where it was as long as there is a pointer to it from somewhere, like the entryArr array. 3) The value is not retrieved from the storage space, instead the array just contains a reference to that space in memory telling it that the object is there. This distinction is important, because the error you had initially occurs because all of the array elements had pointers to the same piece of memory meaning that changing one of them would change all of them. I've attached a short diagram explaining basically how the memory works in this situation. It's not 100% accurate, but it would take at least a semester course to teach the details. 1 Link to comment Share on other sites More sharing options...
iwato Posted September 24, 2018 Author Share Posted September 24, 2018 Thank you, ingolme, for the excellent presentation. As a new object will be added to the current search and recover operation with each new day, the number of objects required to generate the designated graph for which this function was created will soon become very large. It would appear that the two-step approach that you have outlined in the above diagrams is more efficient than the one-step approach initially suggested. What do you think? Roddy Link to comment Share on other sites More sharing options...
Ingolme Posted September 24, 2018 Share Posted September 24, 2018 Both of them are equally efficient, they reserve the same amount of memory and they take the same amount of processing time. The only difference between them is the context in which the memory is reserved. I would recommend with putting the entry variable inside the each() callback only because you don't need it anymore after the process has ended. 1 Link to comment Share on other sites More sharing options...
iwato Posted September 25, 2018 Author Share Posted September 25, 2018 The Furtive Fox strikes again! Thank you for the wonderful elucidation, Ingolme. Roddy Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now