有没有正确的方法来克隆JavaScript中对象的某些原始属性?

时间:2017-06-28 14:52:08

标签: javascript object clone

我需要一个简单的函数来将基本属性列表从一个对象映射到另一个对象。我自己写了一篇,但我想已经有一种行之有效的方法了。

var mapProperties = function (props, from) {
    var to = {};

    for (var i = 0; i < props.length; i++) {
        to[props[i]] = from[props[i]];
    }

    return to;
}

然后使用如下函数:

var fromObj = {
   foo: "foo",
   bar: 1
}

var toObj = mapProperties(['foo', 'bar'], fromObj);

有更好的想法吗?

3 个答案:

答案 0 :(得分:1)

如果您不期待DeepClone,那么您可以使用Object.assign将所有可枚举的自有属性的值从一个或多个源对象复制到目标对象。

var fromObj = {
   foo: "foo",
   bar: 1
}

var targetObject = Object.assign({}, fromObj);
console.log(targetObject);

对于深度克隆,您可以使用JSON.parseJSON.stringify方法。

var fromObj = {
   foo: "foo",
   bar: 1,
   deepClone : { 
      newProp : 2
   }
}

var targetObject =  JSON.parse(JSON.stringify(fromObj));
targetObject.deepClone.newProp = 4;
console.log(targetObject);

答案 1 :(得分:0)

有几种方法可以克隆。如果您只需要一个克隆(您的对象只包含一个级别的基元),Object.assign()是一种方便的方法:

const fromObj = { a: 1, b: 2, c: 3 };
const toObj = Object.assign({}, fromObj);

Object.assign()函数基本上表示&#34;将其他对象的所有属性分配给第一个&#34;。通过使第一个成为空对象,它实际上是一个克隆。

如果您需要更受控制的副本,可以使用Object.keys(),这样您就不会手动拥有列出属性的数组:

&#13;
&#13;
// concise example using reduce and assign
const cloneA = obj => Object.keys(obj).reduce((result, key) => Object.assign(result, { [key]: obj[key] }), {});

// using a for-loop
const cloneB = obj => {
  const result = {};
  const keys = Object.keys(obj);
  
  for(let i in keys) {
    result[keys[i]] = obj[keys[i]];
  }
  
  return result;
}

const fromObj = { a: 1, b: 2, c: 3 };
console.log(cloneA(fromObj));
console.log(cloneB(fromObj));
&#13;
&#13;
&#13;

如果你需要处理其他原语,那么你需要一个深度克隆函数。那里有很多库,所以我不会在这里重新实现一个,但基本上它是我的一个克隆函数的递归版本,它检查它是否是原始的副本。

答案 2 :(得分:0)

这是一个仅按照Object.assign()惯例复制基元的实现:

&#13;
&#13;
function filterPrimitives (key) {
  return !(this[key] instanceof Object)  
}

function clonePrimitives (target) {
  var sources = Array.from(arguments).slice(1)
  
  sources.forEach(function (source) {
    var ownKeys = Object.getOwnPropertyNames(source)
    var primitiveKeys = ownKeys.filter(filterPrimitives, source)
    
    primitiveKeys.forEach(function (key) {
      target[key] = source[key]
    })
  })

  return target
}

var target = {};

var source = {
  a: 'test',
  b: /test/,
  c: 5,
  d: null,
  e: undefined,
  f: {},
  g: []
}

clonePrimitives(target, source, { a: 'override' })

console.log(target)
&#13;
&#13;
&#13;

如果您想要更有效的方法,请使用for循环而不是forEach()

&#13;
&#13;
function clonePrimitives (target) {
  var i, j, source, ownKeys, key

  for (i = 1; i < arguments.length; i++) {
    source = arguments[i]
    ownKeys = Object.getOwnPropertyNames(source)

    for (j = 0; j < ownKeys.length; j++) {
      key = ownKeys[j]

      if (!(source[key] instanceof Object)) {
        target[key] = source[key]
      }
    }
  }

  return target
}

var target = {};

var source = {
  a: 'test',
  b: /test/,
  c: 5,
  d: null,
  e: undefined,
  f: {},
  g: []
}

clonePrimitives(target, source, { a: 'override' })

console.log(target)
&#13;
&#13;
&#13;

最后,一种等效的ES6方法可以让事情变得更好:

&#13;
&#13;
function clonePrimitives (target) {
  for (let source of Array.from(arguments).slice(1)) {
    for (let key of Object.getOwnPropertyNames(source)) {
      if (!(source[key] instanceof Object)) {
        target[key] = source[key]
      }
    }
  }

  return target
}

let target = {};

let source = {
  a: 'test',
  b: /test/,
  c: 5,
  d: null,
  e: undefined,
  f: {},
  g: []
}

clonePrimitives(target, source, { a: 'override' })

console.log(target)
&#13;
&#13;
&#13;