首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更改JavaScript中的局部变量会影响原始全局变量的不同名称

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

Stack Overflow用户
提问于 2015-12-15 18:34:33
回答 2查看 46关注 0票数 0

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

代码语言:javascript
复制
var g_nutrition_summary = null;

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

代码语言:javascript
复制
g_nutrition_summary = json.data;

这一行是变量的唯一赋值,再也不会被调用(用警报测试)。

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

在图表下面,用户可以通过一系列复选框过滤它显示的某些类型的数据。因此,我的目标是,保留网络输入内容的原始值,然后对其进行本地复制,并修改副本(而不是全局原件)并重新填充图表。每次用户选中/取消选中复选框时,它都会调用此函数并获取原始全局(g_nutrition_summary)并重新筛选该函数。

我就是这样做的:

代码语言:javascript
复制
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变量范围不了解吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-15 18:53:36

javascript中的对象和数组都被视为引用,因此,当试图将它们传递给函数或“复制”它们时,您只是在克隆引用。

要获得“真实副本”,您需要遍历该对象并将其内容复制到另一个对象。这可以递归地完成,但幸运的是jquery已经附带了这样一个函数:$.extend

因此,解决办法是:

代码语言:javascript
复制
var tmp_object = $.extend({},g_nutrition_summary);

如果您有一个嵌套对象,则需要设置一个额外的参数:

代码语言:javascript
复制
var tmp_object = $.extend(true,{},g_nutrition_summary); // now it will do it recursively

对于数组来说,制作“真实副本”的一个简单方法就是@Branden指出,

代码语言:javascript
复制
var arrCopy = arrOriginal.slice(0)

关于jquery扩展的更多信息:https://api.jquery.com/jquery.extend/

票数 2
EN

Stack Overflow用户

发布于 2015-12-15 18:39:41

同意朱维安的评论。要将新数组创建为某种程度上的“复制”而不仅仅是引用,请使用:

代码语言:javascript
复制
var tmp_object= g_nutrition_summary.slice(0);

但是,.slice()只适用于数组,不适用于JSON,因此要使用此方法,您必须从JSON创建一个数组

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

代码语言:javascript
复制
var tmp_object= JSON.parse(JSON.stringify(g_nutrition_summary));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34296867

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档