【问题标题】:Object.assign keeps reference to original object [duplicate]Object.assign 保持对原始对象的引用[重复]
【发布时间】:2016-03-24 17:10:53
【问题描述】:

我有方法:

export const groupActivities = ({ activities, tags, images, tickets }) => {
  if (!activities || !tags) {
    console.error('Must have activities and tags');
  }

  const groupActivities = Object.assign({}, activities);

  const groups = groupByTags({ activities: groupActivities, tags });

  groups.forEach(group => {
    group.length = group.activities.length;
    console.log(group.length);
    group.activities.forEach(activity => {
      if (images) {
        activity.images = activity.imageIds.map(id => images[id]);
      }

      if (tickets) {
        console.warn('No tickets provided to the groupactivities helper. May cause problems.');
        activity.tickets = activity.ticketIds.map(id => tickets[id]);
      }
    });
  });

  return groups;
};

Object.assign 正在复制活动对象,但仍保留对它的引用,因此如果我找到特定活动并更改其上的某些属性,它也会更改原始对象! (更改 groupActivities['someID'].name = 'name' 会更改活动对象上的相应活动!)

这会导致一些奇怪的错误。有什么解决办法吗?

使用 babel 5 进行编译。

【问题讨论】:

  • Object.assign 进行浅拷贝,因此子对象引用链接是可以预期的。请参阅“克隆对象”以断开链接。如果您不需要继承、日期或方法,JSON.parse(JSON.stringify(obj)) 可以快速复制普通对象而无需讨厌的外部引用。
  • “有什么解决办法吗?” 做一个深拷贝? What is the most efficient way to clone an object?.
  • 请阅读标签说明! babel 是针对具有该名称的 Python 库的问题。
  • 我确实需要深拷贝,因此我认为Object.assign 会做深拷贝?我没有使用 jquery,只是 es6
  • 是的,不管你听到什么,你现在都有正确的答案了。

标签: javascript babeljs


【解决方案1】:

事实上,这可以通过不同的方式完成:

  1. 如果您不想要外部导入,请实现您拥有的,但要考虑嵌套对象。我实现了我自己的如下(如果你有一个嵌套对象,你需要深度克隆,所以设置deep=true):
function cloneObj(obj, deep=false){
  var result = {};
  for(key in obj){
    if(deep && obj[key] instanceof Object){
       if(obj[key] instanceof Array){
         result[key] = [];
         obj[key].forEach(function(item){
            if(item instanceof Object){
               result[key].push(cloneObj(item, true));
            } else {
               result[key].push(item);
            }
         });
       } else {
         result[key] = cloneObj(obj[key]);
       }
    } else {
       result[key] = obj[key];
    }
  }
  return result
}


// Shallow copy
var newObject = cloneObj(oldObject);
// Deep copy
var newObject = cloneObj(oldObject, true);
  1. 使用 jQuery
// Shallow copy
var newObject = jQuery.extend({}, oldObject);

// Deep copy
var newObject = jQuery.extend(true, {}, oldObject);
  1. 使用UnderscoreJS:
 // Shallow copy
 var newObject = _.clone(oldObject);

PS:我用以下数据测试了我的函数并且工作正常:

var oldObject = {a:1, b:{d:2,c:6}, c:[1,2,{t:1}]};
newObject= cloneObj(oldObject, true);

newObject['b']['d']=8;
newObject['a']=8;
newObject['c'][2]['t']=5;


console.log(oldObject)
console.log(newObject)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    相关资源
    最近更新 更多