Js对象复制的各种姿势(未完成版)

简介: 这个问题来自于在对koa源码的解析之中被再次提起。 源码的位置 github.com/koajs/koa/b…

这个问题来自于在对koa源码的解析之中被再次提起。 源码的位置github.com/koajs/koa/b…



程序中需要从context,request,response模板中复制三个对象,并将其互相挂载起来。这里面用到了Object.create方法。


首先我们先盘一盘如果想达到对象复制都有哪几种办法


为什么我们要复制对象


首先我们看看为什么要复制变量,假设我们用字面量定义一个模板对象, 如果不复制,两个对象其实是引用的同一个对象实例。


const template = {
    data: 1,
}
const objectA = template
template.data = 8
const objectB = template
template.data = 9
console.log('objectA:',objectA)
console.log('objectB:',objectB)
// 运行结果
// objectA: { data: 9 }
// objectB: { data: 9 }
`121


方法一: 解构赋值


解构赋值其实就是利用解构的浅拷贝效应从而达到变量赋值的目的。当然既然是浅拷贝,深层就不行了。


const template = {
    data: 1,
    info: {
        b: 1
    }
}
const objectA = {...template}
objectA.data = 2
objectA.info.b = 8
const objectB = {...template}
objectB.data = 3
objectB.info.b = 9
console.log('objectA:',objectA)
console.log('objectB:',objectB)
// 运行结果
// ============
// objectA: { data: 2, info: { b: 9 } }
// objectB: { data: 3, info: { b: 9 } }


方法二: JSON.stringify & parse


为了解决深层拷贝问题我们可以考虑将源对象转换为字符串,再转换为新对象。


const template = {
    data: 1,
    info: {
        b: 1
    }
}
const objectA = JSON.parse(JSON.stringify(template))
objectA.data = 2
objectA.info.b = 8
const objectB = JSON.parse(JSON.stringify(template))
objectB.data = 3
objectB.info.b = 9
console.log('objectA:',objectA)
console.log('objectB:',objectB)
// 运行结果
// ============
// objectA: { data: 2, info: { b: 8 } }
// objectB: { data: 3, info: { b: 9 } }


方法三:Object.create


看似问题解决了 但是如果我们如果使用了getter和setter方法的话,而且里面又有一个字面量中没有描述的对象,问题就出现了,由于上面两种复制方式都会调用到变量的getter方法,这个时候就会报错。


const template = {
    data: 1,
    info: {
        b: 1
    },
    get c() {
        return this.xxx.data
    }
}



实际上Object.create是做了以对象为原型进行了继承操作 getter/setter方法可以继承过来 但是并不能完成深层copy


const template = {
    data: 1,
    info: {
        b: 1
    },
    get c() {
        return this.xxx.data
    }
}
const objectA = Object.create(template)
objectA.data = 2
objectA.info.b = 8
const objectB = Object.create(template)
objectB.data = 3
objectB.info.b = 9
console.log('objectA:',objectA.__proto__)
console.log('objectA的原型:',objectA.__proto__)
console.log('objectA.data:',objectA.data)
console.log('objectA.info.b:',objectA.info.b)
console.log('objectB的原型:',objectB.__proto__)
console.log('objectB.data:',objectB.data)
console.log('objectB.info.b:',objectB.info.b)
// 运行结果
// ============
// objectA: { data: 1, info: { b: 9 }, c: [Getter] }
// objectA的原型: { data: 1, info: { b: 9 }, c: [Getter] }
// objectA.data: 2
// objectA.info.b: 9
// objectB的原型: { data: 1, info: { b: 9 }, c: [Getter] }
// objectB.data: 3
// objectB.info.b: 9 // 并没有深拷贝


归纳总结


赋值 浅拷贝 深拷贝 getter/setter
解构赋值
JSON.stringify
Object.create


最后我们就知道了在koa源码里面 主要就是要继承原型中的getter/setter所以选择了Object.create方法


相关文章
打印机,如何解决打印机打印有划痕的问题,内部需要清洗,找盆水,清洗,硒鼓盒拆开,怎样更容易放进去,头部朝下的地方先放进去,倾斜向下
打印机,如何解决打印机打印有划痕的问题,内部需要清洗,找盆水,清洗,硒鼓盒拆开,怎样更容易放进去,头部朝下的地方先放进去,倾斜向下
|
9月前
|
C++
当前不会命中断点还未为文档加载任何符号
当前不会命中断点还未为文档加载任何符号
165 2
|
9月前
|
XML JavaScript 前端开发
《原型链重置版》一万多字让你读懂JavaScript原型对象与原型链的继承,探秘属性的查找机制! (6)
其实javascript中很多方面都跟原型链有关系,你如果没有弄懂,就等同于没有学会javascript...
57 1
《原型链重置版》一万多字让你读懂JavaScript原型对象与原型链的继承,探秘属性的查找机制! (6)
|
9月前
|
SQL 前端开发 JavaScript
终于弄懂了Layui表格重载数据(中途被女朋友劝反附聊天记录)
终于弄懂了Layui表格重载数据(中途被女朋友劝反附聊天记录)
207 0
复制一个5G文件只需要两秒,全网最牛方法!
复制一个5G文件只需要两秒,全网最牛方法!