前端那些事

vuePress-theme-reco chenpeng    2020 - 2021
前端那些事 前端那些事

Choose mode

  • dark
  • auto
  • light
首页
文章目录
  • Browser
  • CSS
  • ES6
  • JavaScript
  • Network
  • TypeScript
  • Vue
  • Vue3
  • Webpack
标签
时间轴
GitHub
author-avatar

chenpeng

85

Article

25

Tag

首页
文章目录
  • Browser
  • CSS
  • ES6
  • JavaScript
  • Network
  • TypeScript
  • Vue
  • Vue3
  • Webpack
标签
时间轴
GitHub
  • JS-API

    • new的原理
    • new和Object.create的区别
    • bind、call、apply的区别
    • 如何正确判断this的指向
    • 深拷贝与浅拷贝

深拷贝与浅拷贝

vuePress-theme-reco chenpeng    2020 - 2021

深拷贝与浅拷贝

chenpeng 2020-11-30 JS API

区分浅拷贝与深拷贝:假设 B 复制了 A,如果修改 B,A 也发生变化,就是浅拷贝;如果 A 没有发生变化,就是深拷贝

# 实现浅拷贝

1.for...in 循环赋值(只能拷贝第一层)

function simpleCopy(obj1) {
    let obj2 = Array.isArray(obj1) ? [] : {};
    for(let k in obj1){
        if(obj1.hasOwnProperty(k)){
            obj2[k] = obj1[k];
        }
    }
    return obj2;
}
let obj1 = {
    a: 1,
    b: 2,
    c: {
        d: 3
    }
};
let obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
console.log(obj1.a); // 1
console.log(obj1.c.d); // 4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

2.Object.assign

let obj2 = Object.assign(obj1);
obj2.a = 3;
obj2.c.d = 4;
console.log(obj1.a); // 3
console.log(obj1.c.d); // 4
1
2
3
4
5

3.直接用 = 赋值

let obj2 = obj1;
obj2.a = 3;
obj2.c.d = 4;
console.log(obj1.a); // 3
console.log(obj1.c.d); // 4
1
2
3
4
5

# 实现深拷贝

1.递归拷贝所有层级属性

const objTypes = ['String', 'Number', 'Boolean', 'RegExp', 'Date']

/**
 * 深拷贝,支持数组、正则、函数
 * 利用WeakMap解决循环引用问题
 * @param obj
 * @param map
 * @returns {*[]|any}
 */
function deepClone(obj, map = new WeakMap()) {
    if (!obj || typeof obj !== 'object') {
        return obj
    }
    if (map.has(obj)) {
        return map.get(obj)
    }
    let objType = getObjType(obj)
    if (objTypes.includes(objType)) {
        return new obj.constructor(obj.valueOf())
    }
    let cloneObj = Array.isArray(obj) ? [] : {}
    map.set(obj, cloneObj)
    for (let key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            cloneObj[key] = deepClone(obj[key], map)
        }
    }
    return cloneObj
}

function getObjType(obj) {
    return Object.prototype.toString.call(obj).slice(8, -1)
}
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
29
30
31
32
33

2.通过 JSON 对象来实现深拷贝

function deepCopy(obj1) {
    let obj = JSON.stringify(obj1);
    return JSON.parse(obj);
}
let obj2 = deepCopy(obj1);
1
2
3
4
5

缺点:

  1. 不能拷贝 function、正则、Symbol
  2. 循环引用报错
  3. 相同的引用会被重复拷贝
  4. 无法拷贝对象原型链上的属性和方法

3.通过jQuery的extend方法实现深拷贝

var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝
1
2

4.lodash函数库实现深拷贝

let result = _.cloneDeep(test)
1