当前位置: 代码网 > it编程>编程语言>Javascript > js中对象深拷贝方法总结

js中对象深拷贝方法总结

2024年05月18日 Javascript 我要评论
快速克隆(存在数据丢失问题) – json.parse/stringify如果不在对象中使用date、functions、undefined、infinity、regexps、maps、s

快速克隆(存在数据丢失问题) – json.parse/stringify

如果不在对象中使用date、functions、undefined、infinity、regexps、maps、sets、blob、filelists、imagedatas、或其他复杂类型,则深入克隆对象库可以使用非常简单的一行代码。

简单的来说有以下问题:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象
json.parse(json.stringify(object))
const a = {
  string: 'string',
  number: 123,
  bool: false,
  nul: null,
  date: new date(),  // stringified
  undef: undefined,  // lost
  inf: infinity,  // forced to 'null'
  re: /.*/,  // lost
}
console.log(a);
console.log(typeof a.date);  // date object
const clone = json.parse(json.stringify(a));
console.log(clone);
console.log(typeof clone.date);  // result of .toisostring()

使用第三方框架

由于克隆对象并不简单(复杂类型、循环引用、函数等),大多数主要库都提供了克隆对象的功能。不要重新发明轮子-如果你已经在使用一个库,检查它是否有对象克隆功能。例如:

  • lodash  clonedeep;可以通过lodash.clonedeep模块单独导入,如果之前你没使用过lodash,那么lodash是一个非常不错的选择。
  • angularjs  angular.copy
  • jquery – jquery.extend(true, { }, oldobject).clone() 只能克隆dom

es6

为了完整起见,请注意es6提供了两种浅拷贝机制:object.assign()和拓展运算符语法。它将所有可枚举的自身属性的值从一个对象复制到另一个对象。例如:

var a1 = {a: "2"};
var a2 = object.assign({}, a1);
var a3 = {...a1};  // 拓展运算符

原生实现深拷贝

原生手写深拷贝代码,在面试当中经常遇到,虽然在实际项目开发中不是很常用,但大家还是需要熟练掌握手写代码的思想,因为真的面试经常考到呀~

function deepclone(obj) {
  function isobject(o) {
    return (typeof o === 'object' || typeof o === 'function') && o !== null
  }

  if (!isobject(obj)) {
    throw new error('非对象')
  }

  let isarray = array.isarray(obj)
  let newobj = isarray ? [...obj] : { ...obj }
  reflect.ownkeys(newobj).foreach(key => {
    newobj[key] = isobject(obj[key]) ? deepclone(obj[key]) : obj[key]
  })

  return newobj
}

let obj = {
  a: [1, 2, 3],
  b: {
    c: 2,
    d: 3
  }
}
let newobj = deepclone(obj)
newobj.b.c = 1
console.log(obj.b.c) // 2

messagechannel

messagechannel 也是一个可以实现深拷贝的方式。

function structuralclone(obj) {
  return new promise(resolve => {
    const { port1, port2 } = new messagechannel()
    port2.onmessage = ev => resolve(ev.data)
    port1.postmessage(obj)
  })
}

var obj = {
  a: 1,
  b: {
    c: 2
  }
}

obj.b.d = obj.b

// 注意该方法是异步的
// 可以处理 undefined 和循环引用对象
const test = async () => {
  const clone = await structuralclone(obj)
  console.log(clone)
}
test()
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com