Reputation: 15734
I have a global declared at top of script:
var g_nutrition_summary = null;
When the user enters the page, I return network data and give this variable a value.
g_nutrition_summary = json.data;
This line is the ONLY assignment of the variable and is never called again (tested with alerts).
I later use that json.data
variable to populate a Bar Chart with the plugin Chart.js
. The global assignment is for later use.
Underneath the chart, the user can filter certain types of data it displays with a series of checkboxes. So my goal is, to keep an original value of what comes in from the network, and then make a LOCAL COPY of it and alter the COPY (not the global original) and repopulate the chart. Everytime the user checks/unchecks a checkbox, it will call this function and grab the ORIGINAL global (g_nutrition_summary
) and re-filter that.
Here is how I do it:
function filter_nutrition_log()
{
alert("1: " + JSON.stringify(g_nutrition_summary));
// reassign object to tmp variable
var tmp_object = g_nutrition_summary;
var food_array = new Array("Grains", "Vegetables", "Fruits", "Oils");
var checked_array = new Array();
// Make an array of all choices that are checked
$(".input-range-filter").each(function()
{
var type = $(this).val();
if ($(this).is(':checked'))
{
checked_array.push(type);
}
});
alert("2: " + JSON.stringify(g_nutrition_summary));
// Loop thru all the 7 choices we chart
$.each(food_array, function(i, val)
{
// find out if choice is in array of selected checkboxes
if ($.inArray(val, checked_array) === -1)
{
// it's not, so delete it from out tmp obj we
// will use to repopulate the chart with
// (we do not want to overwrite the original array!)
delete tmp_object["datasets"][val];
}
});
// Resert graph
alert("3: " + JSON.stringify(g_nutrition_summary));
getNutritionChart(null, tmp_object, null, false);
}
Somehow, between alert "1" and alert "2". The global gets changed. Then when the user clicks a checkbox again and it calls this function, the very first alert shows that the original, global object contains the altered data to the tmp_object
variable.
As you can see, I call a third party function I have created when this happens originally. Doing a search for the global there is absolutely nowhere else it is used in the instances described above.
Am I not understanding something about JavaScript variable scope?
Upvotes: 0
Views: 61
Reputation: 16068
Both objects and arrays in javascript are treated as references, so when trying to pass them to functions or to "copy" them, you are just cloning the reference
To have a "real copy", you would need to traverse the object and copy its content to another object. This can be done recursively, but fortunately jquery already comes with a function that does this: $.extend
So the solution would be:
var tmp_object = $.extend({},g_nutrition_summary);
If you have a nested object, you need to set an extra parameter:
var tmp_object = $.extend(true,{},g_nutrition_summary); // now it will do it recursively
For arrays, an easy way to make a "real copy" is, as @Branden Keck pointed out,
var arrCopy = arrOriginal.slice(0)
More on jquery extend: https://api.jquery.com/jquery.extend/
Upvotes: 2
Reputation: 572
Going along with juvian's comment. To create the new array as somewhat of a "copy" and not just a reference, use:
var tmp_object= g_nutrition_summary.slice(0);
However, .slice() is only works for arrays and will not work on JSON, so to used this method you would have to create an array from the JSON
Another method that I found (although not the cleanest) suggested creating a string from the JSON and re-parsing it:
var tmp_object= JSON.parse(JSON.stringify(g_nutrition_summary));
Upvotes: 1