Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

深拷贝和浅拷贝 #18

Open
YIngChenIt opened this issue Jun 30, 2020 · 0 comments
Open

深拷贝和浅拷贝 #18

YIngChenIt opened this issue Jun 30, 2020 · 0 comments

Comments

@YIngChenIt
Copy link
Owner

深拷贝和浅拷贝

浅拷贝

实现浅拷贝的方法一般有2种, Object.assign...xx操作符

const obj = {
    name: 'chenying',
    age: 18,
    has: {
        vue: true
    }
}
const obj1 = {...obj}
obj1.name = 'ying'
console.log(obj) // { name: 'chenying', age: 18, has: { vue: true } }
console.log(obj1) // { name: 'ying', age: 18, has: { vue: true } }
const obj = {
    name: 'chenying',
    age: 18,
    has: {
        vue: true
    }
}
const obj1 = Object.assign(obj)
obj1.name = 'ying'
console.log(obj) // { name: 'ying', age: 18, has: { vue: true } }
console.log(obj1) // { name: 'ying', age: 18, has: { vue: true } }

深拷贝

最简单的深拷贝方法是使用JSON.parse(JSON.stringify(obj))

const obj = {
    name: 'chenying',
    age: 18,
    has: {
        vue: true
    }
}
const obj1 = JSON.parse(JSON.stringify(obj))
obj1.has.vue = false
console.log(obj) // { name: 'chenying', age: 18, has: { vue: true } }
console.log(obj1) // { name: 'chenying', age: 18, has: { vue: false } }

但是这个方法有点缺陷,例如

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

所以一般我们会自己实现一个深拷贝函数

const obj = {
    name: 'chenying',
    age: 18,
    has: {
        vue: true
    }
}

function deepcopy(value) {
    if (value == null) { return value }
    if (value instanceof RegExp) { return new RegExp(value) }
    if (value instanceof Date) { return new Date(value) }
    if (typeof value !== 'object') { return value }
    let obj = new value.constructor() // 拿到[] 或者 {}
    for (let key in value) {
        obj[key] = deepcopy(value[key])
    }
    return obj
}
let obj1 = deepcopy(obj)
obj1.has.vue = false
console.log(obj) // { name: 'chenying', age: 18, has: { vue: true } }
console.log(obj1) //{ name: 'chenying', age: 18, has: { vue: false } }

但是这样写有一个缺陷,就是容易爆栈,例如我们这样调用

let obj2 = {}
obj2.x = obj2
let obj3 = deepcopy(obj2)
console.log(obj3)

那我们可以使用WeakMap的特性判断,如果之前这个值已经拷贝过了,就不需要在进行拷贝了

function deepcopy(value, hash = new WeakMap) {
    if (value == null) { return value }
    if (value instanceof RegExp) { return new RegExp(value) }
    if (value instanceof Date) { return new Date(value) }
    if (typeof value !== 'object') { return value }
    let obj = new value.constructor() // 拿到[] 或者 {}

    if (hash.get(value)) { // 如果hash表里面有这个值就不需要走拷贝了
        return hash.get(value)
    }
    hash.set(value, obj)

    for (let key in value) {
        obj[key] = deepcopy(value[key], hash)
    }
    return obj
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant