【问题标题】:Deep clone without some fields没有某些字段的深度克隆
【发布时间】:2012-12-25 21:01:30
【问题描述】:

让我有下一个 javascript 对象。现在我想克隆它但没有一些字段。例如,我想要没有字段 "lastName""cars.age" 的克隆对象
输入

{
   "firstName":"Fred",
   "lastName":"McDonald",
      "cars":[
           {
              "type":"mersedes",
              "age":5
           },
           {
              "model":"bmw",
              "age":10
           }
       ]
}  

输出(克隆)

{
   "firstName":"Fred",
   "cars":[
       {
          "model":"mersedes"
       },
       {
          "model":"bmw"
       }
   ]
}   

我可以做类似的事情

var human = myJson   
var clone = $.extend(true, {}, human)  
delete clone.lastName  
_.each(clone.cars, function(car))  
{  
   delete car.age  
}  

你知道更简单的解决方案吗?

【问题讨论】:

  • 无法使用$.extend 过滤掉克隆的成员,但您可以推出自己的实现来省略字段...
  • 我将创建一个函数,该函数接受要克隆的对象和要在新对象中删除(或包含)的属性数组。在 jQuery 中没有内置方法可以做到这一点。
  • Underscore.js 包含pluck 函数,这是您想要的一种逆版本:指定您想要包含的内容,而不是您想要省略的内容。也许这可以为您的实施提供一个起点?
  • @Henrik _.pluck 只包含值,没有键
  • @Ilya:哎呀,没关系。

标签: javascript jquery clone deep-copy


【解决方案1】:

如果您不介意添加到对象原型,这是一个简单的解决方案。您可能需要对其进行一些修改以供自己使用。

Object.prototype.deepOmit = function(blackList) {
  if (!_.isArray(blackList)) { 
    throw new Error("deepOmit(): argument must be an Array");
  }

  var copy = _.omit(this, blackList);
  _.each(blackList, function(arg) {
    if (_.contains(arg, '.')) {
      var key  = _.first(arg.split('.'));
      var last = arg.split('.').slice(1);
      copy[key] = copy[key].deepOmit(last);
    }
  });
  return copy;
};

Array.prototype.deepOmit = function(blackList) {
  if (!_.isArray(blackList)) { 
    throw new Error("deepOmit(): argument must be an Array");
  }

  return _.map(this, function(item) {
    return item.deepOmit(blackList);
  });
};

那么当你有一个像这样的对象时:

var personThatOwnsCars = {
   "firstName":"Fred",
   "lastName":"McDonald",
      "cars":[
           {
              "type":"mersedes",
              "age":5
           },
           {
              "model":"bmw",
              "age":10
           }
       ]
};

你可以这样变魔术。

personThatOwnsCars.deepOmit(["firstName", "cars.age"]);

甚至像这样的魔法!

[person1, person2].deepOmit(["firstName", "cars.age"]);

【讨论】:

  • 如果您已经在使用下划线,最好使用_.mixin 而不是原型。
【解决方案2】:

这是一个独立的函数,取决于我写的 lodash/underscore 做同样的事情。

它为对象或数组中的每个 (value, indexOrKey) 对调用回调,如果为 true,则在结果对象中忽略该对。

在访问值后调用回调,因此您可以省略与您的条件匹配的整个值子树。

function deepOmit(sourceObj, callback, thisArg) {
    var destObj, i, shouldOmit, newValue;

    if (_.isUndefined(sourceObj)) {
        return undefined;
    }

    callback = thisArg ? _.bind(callback, thisArg) : callback;

    if (_.isPlainObject(sourceObj)) {
        destObj = {};
        _.forOwn(sourceObj, function(value, key) {
            newValue = deepOmit(value, callback);
            shouldOmit = callback(newValue, key);
            if (!shouldOmit) {
                destObj[key] = newValue;
            }
        });
    } else if (_.isArray(sourceObj)) {
        destObj = [];
        for (i = 0; i <sourceObj.length; i++) {
            newValue = deepOmit(sourceObj[i], callback);
            shouldOmit = callback(newValue, i);
            if (!shouldOmit) {
                destObj.push(newValue);
            }
        }
    } else {
        return sourceObj;
    }

    return destObj;
}

一些样本

var sourceObj = {
    a1: [ undefined, {}, { o: undefined } ],
    a2: [ 1, undefined ],
    o: { s: 's' } 
};

deepOmit(sourceObj, function (value) {
    return value === undefined;
});
//=> { a1: [ {}, {} ], a2: [ 1 ], o: { s: 's' }}

//omit empty objects and arrays too
deepOmit(sourceObj, function (value) {
    return value === undefined ||
        (_.isPlainObject(value) && !_.keys(value).length) ||
        (_.isArray(value) && !value.length);
});
//=> { a2: [ 1 ], o: { s: 's' }}

//indexOrKey is the string key or the numeric index if the object is array
deepOmit([ 0, 1, 2, 3, 4 ], function (value, indexOrKey) {
    return indexOrKey % 2;
});
//=> [ 0, 2, 4 ]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    • 2017-09-01
    • 2010-09-09
    • 1970-01-01
    相关资源
    最近更新 更多