前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS深拷贝与浅拷贝

JS深拷贝与浅拷贝

作者头像
码客说
发布2024-03-29 13:13:22
680
发布2024-03-29 13:13:22
举报
文章被收录于专栏:码客码客

深拷贝

JSON转换

代码语言:javascript
复制
const arr = [1, 2, 3, 4, 5];
const clone = JSON.parse(JSON.stringify(arr));
console.info(clone);

使用JSON.parse(JSON.stringify(arr))的方式进行深拷贝时,并不会拷贝函数。

JSON.stringify()方法会忽略JavaScript对象中的函数成员,并将其转换为空值。

因此,在使用JSON.parse(JSON.stringify(arr))时,任何函数成员都将丢失并转换为undefined

使用 JSON.parse(JSON.stringify(arr)) 进行深拷贝的方式相对简单且易于理解,适合用于处理普通的数据结构。

然而,它无法正确地处理一些特殊类型的数据,例如函数、正则表达式、日期对象等,因为这些类型在 JSON 格式中无法正确表示。

MessageChannel

使用MessageChannel实现深拷贝。

MessageChannel除了用作通信还有一些hack的用法,比如用它来做deepClone。

代码语言:javascript
复制
function deepClone(target) {
    return new Promise(resolve => {
        const channel = new MessageChannel()
        channel.port2.postMessage(target)
        channel.port1.onmessage = eve => {
            resolve(eve.data)
        }
    })
}

使用

代码语言:javascript
复制
const obj = {
    name: '123',
    b: {
        c: 456
    },
    d: undefined
}

deepClone(obj).then(d => console.log(d))

这个方法比较优秀的地方在于undefined的不会丢失,循环引用的对象也不会报错,循环点会被置为undefined,不过不能复制函数。

使用 MessageChannel 实现异步深拷贝,可以正确地处理任何类型的数据,包括特殊类型。

由于它是异步的方式,所以性能可能会受到一定影响,特别是在处理大型数据结构时会更明显。

自定义方法

代码语言:javascript
复制
function deepClone(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  const clone = Array.isArray(obj) ? [] : {};

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key]);
    }
  }

  return clone;
}

使用

代码语言:javascript
复制
const obj = { a: 1, b: { c: 2 }, d: [3, 4],getValue(){
    return this.a;
}};
const clonedObj = deepClone(obj);
console.log(clonedObj);

这种方式会拷贝方法。

浅拷贝

方式1

使用展开运算符可以轻松地复制

代码语言:javascript
复制
const arr = [1, 2, 3, 4, 5];
const clone = [...arr]; 
console.info(clone);

方式2

使用数组的slice方法复制数组

代码语言:javascript
复制
const arr = [1, 2, 3, 4, 5];
const clone = arr.slice();
console.info(clone);

slice() 是数组对象的一个方法,用于从数组中提取指定位置的元素创建一个新的数组。

slice() 方法不会修改原始数组,而是返回一个浅拷贝(shallow copy)的新数组。

slice() 方法可以接收两个参数,即 startend。起始位置 start 是要提取的起始索引(包含在提取范围内),结束位置 end 是要提取的结束索引(不包含在提取范围内)。

如果省略 end 参数,默认会提取到数组的末尾。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-01-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 深拷贝
    • JSON转换
      • MessageChannel
        • 自定义方法
        • 浅拷贝
          • 方式1
            • 方式2
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档