这个问题来自于在对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方法