深拷贝浅拷贝

深拷贝、浅拷贝的区别

新对象(数组)引用旧对象(数组),改变旧对象(数组)的值,如果新对象(数组)的值也跟着改变,即浅拷贝;
如果不影响,即深拷贝

// 1. 数组
// 适用于深拷贝一层数组且值为基本类型的方法有:遍历属性、slice、concat、Object.assign(只有一个参数则为浅拷贝)
var arr = [1, 2, 3, 4, 5]
// var arr = [
//     {number: 111},
//     {number: 222},
//     {number: 333}
// ]

function copy(arr){
    var newArr = []
    for(let item in arr){
        newArr.push(arr[item])
    }
    return newArr
}

var arr1 = copy(arr)

var arr2 = arr.slice()  //arr.slice(0)

var arr3 = arr.concat()

var arr4 = []
Object.assign(arr4, arr)

arr[0] = 100
// arr[0].number = 100

console.log('arr```````', arr)     // [100, 2, 3, 4, 5]
console.log('arr1```````', arr1)   // [1, 2, 3, 4, 5]
console.log('arr2```````', arr2)   // [1, 2, 3, 4, 5]
console.log('arr3```````', arr3)   // [1, 2, 3, 4, 5]
console.log('arr4``````', arr4)    // [1, 2, 3, 4, 5]
// 2. 对象(一层)
var obj = {
    a: 1,
    1: 'aaa',
    b: 2,
    2: 'bbb'
}

function copy1(obj){
    var newObj = {}
    for(var item in obj){
        newObj[item] = obj[item]
    }
    return newObj
}

var obj1 = copy1(obj)

var obj2 = JSON.parse(JSON.stringify(obj))

obj.c = '333'

console.log('obj````````', obj)            // {1: "aaa", 2: "bbb", a: 1, b: 2, c: "333"}
console.log('obj1````````', obj1)          // {1: "aaa", 2: "bbb", a: 1, b: 2}             
console.log('obj2````````', obj2)          // {1: "aaa", 2: "bbb", a: 1, b: 2}
// 所有层级
// 1. JSON.stringify(obj) + JSON.parse()

// 2. 递归复制所有层级属性
function deepCopy(obj){
    let newObj = Array.isArray(obj) ? [] : {}
    if(obj && typeof obj === 'object'){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                if(obj[key] && typeof obj[key] === 'object'){
                    newObj[key] = deepCopy(obj[key])
                }else {
                    newObj[key] = obj[key]
                }
            }
        }
    }
    return newObj   
}

let arr = [1, 2, 3, 4, 5]
let arr1 = deepCopy(arr)

arr[0] = 100

console.log(arr, arr1)  
// [100, 2, 3, 4, 5]   
// [1, 2, 3, 4, 5]

let obj = {
    a: {
        aaa: 1
    },
    1: 'aaa',
    b: 2,
    2: 'bbb'
}

let obj1 = deepCopy(obj)
obj.a.aaa = 111

console.log(obj, obj1)  
// {1: "aaa", 2: "bbb", a: {aaa: 111}, b: 2}  
// {1: "aaa", 2: "bbb", a: {aaa: 1}, b: 2} 


// 3. jquery的extend方法(不适用与IE11及以下)
var obj1 = $.extend(true, {}, obj);
obj.a.aaa = 111;

console.log(obj, obj1);
// {1: "aaa", 2: "bbb", a: {aaa: 111}, b: 2}  
// {1: "aaa", 2: "bbb", a: {aaa: 1}, b: 2}
JSON.stringify() 的缺点

JSON.parse(JSON.stringify(obj))

  • 对象里的时间对象,会变成字符串形式,而不是对象的形式
typeof test.date[0]  // 'object'
typeof copyed.date[0]  // 'string'
  • 对象里的正则、Error对象,会变成空对象
test.reg // /\w+/
copyed.reg // {}
  • 对象里的undefined、function,会过滤掉
  • 对象里的NaN、Infinity、-Infinity,会变成null
  • 对象里的构造函数生成的对象,会丢失掉原本对象的constructor
let a, b = NaN, c = Infinity, d = -Infinity;

function Person (name) {
    this.name = name
}
const jack = new Person('Jack')

let test = {
    name: 'a',
    date: [new Date(1536627600000), new Date(1540047600000)],
    reg: new RegExp('\\w+'),
    fn: function () {},
    a,
    b,
    c,
    d,
    person: jack
};

let copyed = JSON.parse(JSON.stringify(test))

// copyed
{
    b: null,
    c: null,
    d: null,
    date: ['2018-09-11T01:00:00.000Z', '2018-10-20T15:00:00.000Z'],
    name: "a",
    person: {name: 'Jack'},
    reg: {}
}
jack.constructor // ƒ Person (name) { this.name = name }
copyed.person.constructor  // ƒ Object() { [native code] }

results matching ""

    No results matching ""