js中对象如何实现深拷贝

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

如果不在对象中使用Date、functions、undefined、Infinity、RegExps、Maps、Sets、blob、FileLists、ImageDatas、或其他复杂类型,则深入克隆对象库可以使用非常简单的一行代码。

简单的来说有以下问题:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象

1

JSON.parse(JSON.stringify(object))

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

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()

ES6

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

1

2

3

var A1 = {a: "2"};

var A2 = Object.assign({}, A1);

var A3 = {...A1};  // 拓展运算符

原生实现深拷贝

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

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 也是一个可以实现深拷贝的方式。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下次一定L_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值