我在脚本顶部声明了一个全局:
var g_nutrition_summary = null;
当用户进入页面时,我返回网络数据并为该变量赋值。
g_nutrition_summary = json.data;
此行是变量的唯一赋值,永远不会再次调用(使用警报进行测试)。
我稍后使用json.data
变量用插件Chart.js
填充条形图。全局分配供以后使用。
在图表下方,用户可以使用一系列复选框过滤显示的某些类型的数据。因此,我的目标是保持网络内容的原始值,然后对其进行本地复制并更改COPY(不是全局原始版本)并重新填充图表。每次用户选中/取消选中一个复选框时,它都会调用此函数并获取ORIGINAL全局(g_nutrition_summary
)并重新过滤。
我是这样做的:
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);
}
不知何故,警报“1”和警报“2”之间。全球变了。然后,当用户再次单击一个复选框并调用此函数时,第一个警报会显示原始的全局对象包含已更改为tmp_object
变量的数据。
正如您所看到的,我调用了最初发生时创建的第三方函数。搜索全局,在上述实例中使用它绝对没有其他地方。
我不了解JavaScript变量范围吗?
答案 0 :(得分:2)
javascript中的对象和数组都被视为引用,因此在尝试将它们传递给函数或者复制"他们,你只是克隆了参考文献
要拥有"真实副本",您需要遍历该对象并将其内容复制到另一个对象。这可以递归完成,但幸运的是jquery已经附带了一个执行此操作的函数:$.extend
所以解决方案是:
var tmp_object = $.extend({},g_nutrition_summary);
如果您有嵌套对象,则需要设置一个额外的参数:
var tmp_object = $.extend(true,{},g_nutrition_summary); // now it will do it recursively
对于数组,一种简单的方法来制作一个真正的副本"就像@Branden Keck指出的那样,
var arrCopy = arrOriginal.slice(0)
有关jquery extend的更多信息:https://api.jquery.com/jquery.extend/
答案 1 :(得分:1)
赞同juvian的评论。要创建一个新的数组作为一个" copy"而不只是一个参考,使用:
var tmp_object= g_nutrition_summary.slice(0);
但是,.slice()仅适用于数组,不适用于JSON,因此要使用此方法,您必须从JSON创建数组
我找到的另一种方法(虽然不是最干净的)建议从JSON创建一个字符串并重新解析它:
var tmp_object= JSON.parse(JSON.stringify(g_nutrition_summary));