这是在ES6中克隆对象的好方法吗?

2020/10/28 19:22 · javascript ·  · 0评论

谷歌搜索“ javascript克隆对象”会带来一些非常奇怪的结果,其中有些绝望地过时,而有些则过于复杂,难道不是那么简单:

let clone = {...original};

这有什么问题吗?

对于浅克隆是有益物体传播是ECMAScript的2018的标准组成部分

要进行深克隆,您将需要其他解决方案

const clone = {...original} 浅表克隆

const newobj = {...original, prop: newOne} 以不变的方式将另一个道具添加到原始对象并存储为新对象。

编辑:发布此答案时,{...obj}语法在大多数浏览器中不可用。如今,您应该可以很好地使用它(除非您需要支持IE 11)。

使用Object.assign。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

However, this won't make a deep clone. There is no native way of deep cloning as of yet.

EDIT: As @Mike 'Pomax' Kamermans mentioned in the comments, you can deep clone simple objects (ie. no prototypes, functions or circular references) using JSON.parse(JSON.stringify(input))

如果您使用的方法不适用于涉及数据类型(例如Date)的对象,请尝试以下操作

进口 _

import * as _ from 'lodash';

深度克隆对象

myObjCopy = _.cloneDeep(myObj);

如果您不想使用json.parse(json.stringify(object)),则可以递归创建键值副本:

function copy(item){
  let result = null;
  if(!item) return result;
  if(Array.isArray(item)){
    result = [];
    item.forEach(element=>{
      result.push(copy(element));
    });
  }
  else if(item instanceof Object && !(item instanceof Function)){ 
    result = {};
    for(let key in item){
      if(key){
        result[key] = copy(item[key]);
      }
    }
  }
  return result || item;
}

但是最好的方法是创建一个可以自我返回其副本的类

class MyClass{
    data = null;
    constructor(values){ this.data = values }
    toString(){ console.log("MyClass: "+this.data.toString(;) }
    remove(id){ this.data = data.filter(d=>d.id!==id) }
    clone(){ return new MyClass(this.data) }
}

@marcel给出的答案之后,我发现克隆的对象上仍然缺少一些功能。例如

function MyObject() {
  var methodAValue = null,
      methodBValue = null

  Object.defineProperty(this, "methodA", {
    get: function() { return methodAValue; },
    set: function(value) {
      methodAValue = value || {};
    },
    enumerable: true
  });

  Object.defineProperty(this, "methodB", {
    get: function() { return methodAValue; },
    set: function(value) {
      methodAValue = value || {};
    }
  });
}

在MyObject上我可以克隆methodA的位置,但不包括methodB。发生这种情况是因为缺少

enumerable: true

这意味着它没有出现在

for(let key in item)

相反,我切换到

Object.getOwnPropertyNames(item).forEach((key) => {
    ....
  });

其中将包含不可枚举的密钥。

我还发现原型(proto)没有被克隆。为此,我最终使用

if (obj.__proto__) {
  copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}

PS:令人沮丧的是我找不到内置函数来执行此操作。

您也可以这样做

let copiedData = JSON.parse(JSON.stringify(data));

上面的所有方法都无法处理嵌套到n个层的对象的深度克隆。我没有检查它在其他方面的性能,但是它简短而简单。

下面的第一个示例显示了使用对象克隆Object.assign直到第一级的对象克隆

var person = {
    name:'saksham',
    age:22,
    skills: {
        lang:'javascript',
        experience:5
    }
}

newPerson = Object.assign({},person);
newPerson.skills.lang = 'angular';
console.log(newPerson.skills.lang); //logs Angular

使用以下方法深度克隆对象

var person = {
    name:'saksham',
    age:22,
    skills: {
        lang:'javascript',
        experience:5
    }
}

anotherNewPerson = JSON.parse(JSON.stringify(person));
anotherNewPerson.skills.lang = 'angular';
console.log(person.skills.lang); //logs javascript
We can do that with two way:
1- First create a new object and replicate the structure of the existing one by iterating 
 over its properties and copying them on the primitive level.

let user = {
     name: "John",
     age: 30
    };

    let clone = {}; // the new empty object

    // let's copy all user properties into it
    for (let key in user) {
      clone[key] = user[key];
    }

    // now clone is a fully independant clone
    clone.name = "Pete"; // changed the data in it

    alert( user.name ); // still John in the original object

2- Second we can use the method Object.assign for that 
    let user = { name: "John" };
    let permissions1 = { canView: true };
    let permissions2 = { canEdit: true };

    // copies all properties from permissions1 and permissions2 into user
    Object.assign(user, permissions1, permissions2);

  -Another example

    let user = {
      name: "John",
      age: 30
    };

    let clone = Object.assign({}, user);
It copies all properties of user into the empty object and returns it. Actually, the same as the loop, but shorter.

But Object.assign() not create a deep clone

let user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50
  }
};

let clone = Object.assign({}, user);

alert( user.sizes === clone.sizes ); // true, same object

// user and clone share sizes
user.sizes.width++;       // change a property from one place
alert(clone.sizes.width); // 51, see the result from the other one

To fix that, we should use the cloning loop that examines each value of user[key] and, if it’s an object, then replicate its structure as well. That is called a “deep cloning”.

有一个用于深度克隆的标准算法(结构化克隆算法)可以处理上述情况和更复杂的情况为了避免重新发明轮子,我们可以从JavaScript库lodash中使用它的有效实现,该方法称为_.cloneDeep(obj)

本文地址:http://javascript.askforanswer.com/zheshizaies6zhongkelongduixiangdehaofangfama.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!