在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莴苣抱歉放弃