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方法


相关文章
|
JavaScript
动态给vue的data添加一个新的属性时会发生什么?怎样解决?
动态给vue的data添加一个新的属性时会发生什么?怎样解决?
179 1
|
移动开发
微信h5扫码接口范例:多个扫码框支持的办法,通过引入一个参数来区分及使用localStorage保证之前扫到的数据不丢失
微信h5扫码接口范例:多个扫码框支持的办法,通过引入一个参数来区分及使用localStorage保证之前扫到的数据不丢失
105 0
|
前端开发
前端学习案例-严格模式2-对象的静默失败
前端学习案例-严格模式2-对象的静默失败
74 0
前端学习案例-严格模式2-对象的静默失败
element close事件关闭表单,数据替换掉原始列表的数据bug解决
element close事件关闭表单,数据替换掉原始列表的数据bug解决
61 0
|
前端开发
【React工作记录四十】对象的属性和值转换
【React工作记录四十】对象的属性和值转换
94 0
|
前端开发
【React工作记录三十八】对象的属性和值转换
【React工作记录三十八】对象的属性和值转换
68 0
|
前端开发 数据格式
#yyds干货盘点 【React工作记录五】如何处理数据格式字符串让它加上标签
#yyds干货盘点 【React工作记录五】如何处理数据格式字符串让它加上标签
87 0
#yyds干货盘点 【React工作记录五】如何处理数据格式字符串让它加上标签
|
存储 JavaScript 前端开发
手撕前端面试题【javascript~文件扩展名、分隔符、单向绑定、判断版本、深浅拷贝、内存泄露等】
手撕前端面试题【javascript~文件扩展名、分隔符、单向绑定、判断版本、深浅拷贝、内存泄露等】
237 0
手撕前端面试题【javascript~文件扩展名、分隔符、单向绑定、判断版本、深浅拷贝、内存泄露等】
|
前端开发
#yyds干货盘点# 【React工作记录四十】对象的属性和值转换
#yyds干货盘点# 【React工作记录四十】对象的属性和值转换
124 0
#yyds干货盘点# 【React工作记录四十】对象的属性和值转换
|
前端开发
#yyds干货盘点# 【React工作记录三十八】对象的属性和值转换
#yyds干货盘点# 【React工作记录三十八】对象的属性和值转换
143 0
#yyds干货盘点# 【React工作记录三十八】对象的属性和值转换