5.JS-浅拷贝和深拷贝

104 阅读2分钟

什么是浅拷贝?如何实现浅拷贝?什么是深拷贝?如何实现深拷贝?

对象类型在赋值的过程中其实是复制了地址,从而会导致改变了一方其他也都被改变的情况。通常在开发中我们不希望出现这样的问题,我们可以使用浅拷贝和深拷贝来解决问题;但是浅拷贝只解决了第一层的问题,如果里面的值有对象的话就需要用深拷贝了


★ 浅拷贝

1.Object.assign

2.展开运算符 ...

★ 深拷贝

1.JSON.parse(JSON.stringify(object))

但是该方法也是有局限性的:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象
  • 在遇到函数、 undefined 或者 symbol 的时候,该对象也不能正常的序列化

2.MessageChannel

3.lodash 的深拷贝函数

www.lodashjs.com/docs/lodash…

// 使用
import _ = form 'lodash';

var objects = [{ 'a': 1 }, { 'b': 2 }];

var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);// => false

4.自定义深拷贝

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

★ Reflect.ownKeys和Object.keys的区别

jishuin.proginn.com/p/763bfbd64…

1.关于对象属性是否可枚举

Reflect.ownKeys()可以得到对象自己的所有属性,包括不可枚举属性
Object.keys()只能得到对象的普通可枚举属性,拿不到不可枚举属性。

2.关于Symbol属性

Reflect.ownKeys()可以拿到对象的Symbol 的属性;
Object.keys()不行

3.关于数组的length属性

因为Reflect.ownKeys()可以得到对象的不可枚举属性这个特点,所以当目标对象是数组对象时,我们可以看到获取的结果会比Object.keys()多一个length属性

事实证明,数组的length也确实是“不可枚举的”:

4.关于对象的原型

俩人这点上谁也不比谁强,都拿不到原型链上的属性。

不过还好,这点需求上,可以用for...in来替代。

总结表格

方法分类普通属性不可枚举属性Symbol属性原型属性数组length
Reflect.ownKeys()
Object.keys()
for...in