js中对象深拷贝方法总结

快速克隆(存在数据丢失问题) – 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()

更多关于js中对象深拷贝方法请查看下面的相关链接

(0)

相关推荐

  • Javascript Object对象类型使用详解

    目录 1. 生成方法 2. 操作属性 2.1 读取 2.2 赋值 2.3 删除 2.4 遍历 2.5 判断属性是否存在 3. with 语句 总结 1. 生成方法 对象是javaScript中的一种数据类型,它是key-value的合集,是无序的 const obj = { name: 'ian',age: 21}; //key使用变量 const gender = 'gender'; const obj = { [gender]: 'male'}; 对象的key必须符合标识符的规则,写的时候k

  • 纯 JS 实现的轻量化图片编辑器实例详解

    目录 介绍 一款纯 JS 实现的轻量化图片编辑器 Optimizer 框架特点 Optimizer 框架使用 启动 场景管理器 (Scene) 页面事件Event 鼠标事件 键盘事件 注册组件 Component 使用组件 总结 介绍 因为一些特点的工作场景, 写文章的需要每次处理一些图片, 在上面加说明文字, 或者加一些图形 刚开始使用 PPT 来处理, 一张张复制过去, 做一些边框阴影处理, 再加一些图形, 然后再导出来复制到需要的地方, 而且导出后的图片之后可能不会再使用了还要清理. 图片

  • JavaScript中原始值和引用值深入讲解

    目录 值和引用相关内容 1. 简单值(原始值) 2. 复杂值(引用值) 3. 访问方式 4. 比较方式 5. 动态属性 6. 变量赋值 灵魂拷问 总结 值和引用相关内容 在 JavaScript 中,数据类型整体上来讲可以分为两大类:基本类型和引用数据类型 基本数据类型,一共有 6 种: string,symbol,number,boolean,undefined,null 其中 symbol 类型是在 ES6 里面新添加的基本数据类型. 引用数据类型,就只有 1 种: object 基本数据类

  • JavaScript代码优雅,简洁的编写技巧总结

    1. 强类型检查 用===代替 == // 如果处理不当,它会极大地影响程序逻辑.这就像,你想向左走,但由于某种原因,你向右走 0 == false // true 0 === false // false 2 == "2" // true 2 === "2" // false // 例子 const value = "500"; if (value === 500) { console.log(value); // 条件不成立,不会进入 } i

  • JavaScrip将数组转为对象与JSON对象字符串转数组方法详解

    JavaScrip将数组转为对象(JS数组转对象工作经常用) 我想获取一个元素数组,并将它们转换为一个对象.数组中的元素需要是对象的键,带有一些默认的空字符串,作为以后要更改的值. ['name','age','city', 'town', 'country'] { name: "", age: "", city: "", town: "", country: "" } 最后我发现我们可以使用数组的redu

  • JavaScript 弱引用强引用底层示例详解

    目录 正文 1. 弱引用 2. 强引用 3. JavaScript 的垃圾收集 3.1 可达性 4. Set VS WeakSet 5. Map VS WeakMap 6. WeakMap 的应用 6.1 缓存 6.2 额外的数据存储 7. 小结 正文 内存和性能管理是软件开发的重要方面,也是每个软件开发人员都应该注意的方面.虽然弱引用很有用,但在 JavaScript 中并不经常使用.在 ES6 版本中,JavaScript 引入了 WeakSet 和 WeakMap. 1. 弱引用 与强引用

  • JavaScript日拱算法题解滑动窗口的最大值示例

    目录 题目: 题解: 第一反应 JavaScript 实现 第二反应 JS 实现 小结: 题目: 给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值. 示例: 输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3 输出: [3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6

  • js中对象深拷贝方法总结

    快速克隆(存在数据丢失问题) – JSON.parse/stringify 如果不在对象中使用Date.functions.undefined.Infinity.RegExps.Maps.Sets.blob.FileLists.ImageDatas.或其他复杂类型,则深入克隆对象库可以使用非常简单的一行代码. 简单的来说有以下问题: 会忽略 undefined 会忽略 symbol 不能序列化函数 不能解决循环引用的对象 JSON.parse(JSON.stringify(object)) co

  • js中区分深拷贝与浅拷贝的实战过程

    目录 一.自我理解 二.数据存储形式 (1)基本数据类型存储于栈中 (2)引用数据类型存储与堆中 三.怎样实现深拷贝? (1)借助JSON对象的parse和stringify (2)手写递归 (3)JQuery中extend方法 总结/注意 总结 一.自我理解 简单来讲就是:深拷贝层层拷贝,浅拷贝只拷贝第一层. 在深拷贝中,新对象中的更改不会影响原对象,而在浅拷贝中,新对象中的更改,原对象中也会跟着改. 在深拷贝中,原对象与新对象不共享相同的属性,而在浅拷贝中,它们具有相同的属性. 举个栗子:存

  • 使用JS中的exec()方法构造正则表达式验证

    正则表达式,又称正规表示法.常规表示法.(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则.在很多文本编辑器里,正则表达式通常被用来检索.替换那些符合某个模式的文本. 一.Javascript中的正则表达式 在Javascript中,可以使用RegExp对象构造正则表达.我们需要新建一个实例化的RegExp()对象,可以传入两个参数:第一个参数是匹配的模式,第二个参数是一

  • 使用JS中的Replace()方法遇到的问题小结

    今天在写pc客户端自动化打包脚本的时候遇到遇到了几个问题,虽然是小问题,但是也卡了一段时间,所以决定记录一下. js的replace()方法是用于替换某些内容,它可以接收两个参数,第一个是一个被替换的正则表达式对象或者一个字符串,第二个可以是将要替换成的内容或者函数,将要替换成的内容须是一个字符串.我在执行的时候遇到的报错是:Cannot read property 'replace' of undefined.具体代码如下: var fs=require("fs") var info

  • 浅谈js中对象的使用

    简单记录javascript中对象的使用 一.创建对象 //创建一个空对象 var o={}; //创建一个含有两个属性的对象,x.y var o2={x:12,y:'12',name:'JS'}; //此对象中的author属性的值还是一个对象 var o3={x:12,author:{name:'JS',age:23,address:'china'}}; //创建一个空对象和{}一样 var o4=new Object(); //给对象增加name属性 o4.name='JS' 上面使用了两

  • 遍历js中对象的属性和值的实例

    今天优化项目时,遇到了关于"遍历js中对象的属性和值"的需求.之所以会有这个需求,是因为要做一个局部刷新表格内容的js插件.刚开始我去网上荡了一个js分页插件,但是智商实在捉急,搞了半天没搞出来!后来就怒了,干脆自己写一个好了.结果就遇到了这个问题! 问题:通过遍历属性名数组,获取对象的属性值失败 刚开始的错误代码如下: for(var i=0;i<dataList.length;i++) { var dataLine="<tr>"; for(va

  • JS中的数组方法笔记整理

    push()方法:可以向数组的末尾添加一个或者多个元素,并且返回新的长度 pop()方法:可以删除数组最后一个元素,并且返回被删除的元素,注意:如果数组是空的,该方法不进行任何操作,返回undefined. unshift()方法:可以向数组的开头添加一个或者多个元素,并且返回新的长度 shift()方法:可以删除数组第一个元素,并且返回被删除的元素,注意:如果数组是空的,该方法不进行任何操作,返回undefined. splice()方法:从数组中添加/删除项目,然后返回被删除的项目,该方法会

  • JS中对象与字符串的互相转换详解

    在使用 JSON2.JS 文件的 JSON.parse(data) 方法时候,碰到了问题: throw new SyntaxError('JSON.parse'); 查询资料,大概意思如下: JSON.parse方法在遇到不可解析的字符串时,会抛出SyntaxError异常. 即:JSON.parse(text, reviver),This method parses a JSON text to produce an object or array. t can throw a SyntaxE

  • JS中的reduce()方法使用小结

    目录 一.语法 二.实例 三.其他相关方法 过去有很长一段时间,我一直很难理解 reduce() 这个方法的具体用法,平时也很少用到它.事实上,如果你能真正了解它的话,其实在很多地方我们都可以用得上,那么今天我们就来简单聊聊JS中 reduce() 的用法. 一.语法 arr.reduce(function(prev,cur,index,arr){ ... }, init); 其中, arr 表示原数组: prev 表示上一次调用回调时的返回值,或者初始值 init; cur 表示当前正在处理的

  • JS中Object.assign方法的使用

    最在做项目过程中,大量的使用了Object.assign方法,发现这个还是挺好使用的,现在总结下Object.assign的基本使用. 一.基本语法 Object.assign(target, ...sources) 二.基本概念 Object.assign方法用来将源对象(source)的所有可枚举属性,复制到目标对象(target).它至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象.只要有一个参数不是对象,就会抛出TypeError错误. 三.基本用途 1.合并多个对象

随机推荐