在JavaScript中更改局部变量会影响具有不同名称的原始全局变量

在JavaScript中更改局部变量会影响具有不同名称的原始全局变量,javascript,jquery,global-variables,Javascript,Jquery,Global Variables,我在脚本顶部声明了一个全局变量: var g_nutrition_summary = null; 当用户进入页面时,我返回网络数据并给这个变量一个值 g_nutrition_summary = json.data; 这一行是变量的唯一赋值,不再调用(使用警报测试) 稍后,我使用json.data变量用插件Chart.js填充条形图。全局分配供以后使用 在图表下方,用户可以通过一系列复选框过滤显示的特定类型的数据。因此,我的目标是,保留来自网络的内容的原始值,然后制作其本地副本,更改副本(而不

我在脚本顶部声明了一个全局变量:

var g_nutrition_summary = null;
当用户进入页面时,我返回网络数据并给这个变量一个值

g_nutrition_summary = json.data;
这一行是变量的唯一赋值,不再调用(使用警报测试)

稍后,我使用
json.data
变量用插件
Chart.js
填充条形图。全局分配供以后使用

在图表下方,用户可以通过一系列复选框过滤显示的特定类型的数据。因此,我的目标是,保留来自网络的内容的原始值,然后制作其本地副本,更改副本(而不是全局原始副本)并重新填充图表。每次用户选中/取消选中复选框时,它将调用此函数并获取原始全局(
g\u nutrition\u 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_对象
变量的更改数据

如您所见,我调用了我最初创建的第三方函数。在上面描述的实例中,搜索全局搜索绝对没有其他地方使用它


我对JavaScript变量作用域有什么不了解吗?赞同朱维安的评论。要将新数组创建为“副本”而不仅仅是引用,请使用:

var tmp_object= g_nutrition_summary.slice(0);
但是,.slice()仅适用于数组,不适用于JSON,因此要使用此方法,必须从JSON创建数组

我发现的另一个方法(虽然不是最干净的)建议从JSON创建一个字符串并重新解析它:

var tmp_object= JSON.parse(JSON.stringify(g_nutrition_summary));

同意朱维安的评论。要将新数组创建为“副本”而不仅仅是引用,请使用:

var tmp_object= g_nutrition_summary.slice(0);
但是,.slice()仅适用于数组,不适用于JSON,因此要使用此方法,必须从JSON创建数组

我发现的另一个方法(虽然不是最干净的)建议从JSON创建一个字符串并重新解析它:

var tmp_object= JSON.parse(JSON.stringify(g_nutrition_summary));

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的更多信息:

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扩展的更多信息:

var tmp\u object=g\u nutrition\u summary
tmp_对象
不是副本,它只是对
g_营养总结
对象的引用。要真正复制,您需要使用
tmp\u object=$.extend({},g\u nutrition\u summary)
@juvian我对此一无所知。(显然)
var tmp_object=g_nutrition_summary
tmp_对象
不是副本,它只是对
g_营养总结
对象的引用。要真正复制,您需要使用
tmp\u object=$.extend({},g\u nutrition\u summary)
@juvian我对此一无所知。(显然)当我这样做时,它说
slice
不是一个函数?请记住,全局是一个对象(如果这有区别的话)。是的,对于数组来说,这是正确的答案,我认为json.data是一个对象,尽管他做的是
tmp_对象[“数据集”]
@juvian correct。对象中有一些数据是我在上面的函数中循环通过的数组。@Kicking莴苣抱歉,上次我使用JSON时,我在更改之前先将其放入数组中,这就是slice对我有效的原因,我将编辑我的答案来说明这一点,并继续寻找更好的解决方案注意,使用parse+stringify方法,如果你有一个对象而不是json,它会在我这样做的时候失去它的函数,它说
slice
不是函数?请记住,全局是一个对象(如果这有区别的话)。是的,对于数组来说,这是正确的答案,我认为json.data是一个对象,尽管他做的是
tmp_对象[“数据集”]
@juvian correct。对象中有一些数据是我在上面的函数中循环通过的数组。@Kicking莴苣抱歉,上次我使用JSON时,我在更改之前先将其放入数组中,这就是slice对我有效的原因,我将编辑我的答案来说明这一点,并继续寻找更好的解决方案注意,使用parse+stringify方法,如果你有一个对象而不是json,它会像我尝试的
extend
一样丢失它的函数,但效果相同。没有控制台错误,只是更改了原始版本。我将再次验证。@kickings抱歉忘记了一个参数,请检查更新的答案。这里有一个简单的例子:好的,就是这样。谢谢你的帮助!我尝试了
扩展
,但效果相同。没有控制台错误,只是更改了原始版本。我要再核实一下。@Kicking莴苣抱歉放弃