目录
浅拷贝
什么是浅拷贝?
只把对象上第一层的属性拷贝一份, 放到一个新对象上
如果浅拷贝的属性指向的是一个对象或者一个数组, 那么它拷贝的是这个对象或数组的内存地址
浅拷贝代码演示:
// 浅拷贝:只把对象上第一层的属性拷贝一份,放到一个新对象上!!!
function simpleCopy(obj) {
// 通过 "Array.isArray()"方法 判断用户传进来的 obj 是“数组”还是“真正的对象”
const newObj = Array.isArray(obj) ? [] : {}
// 循环对象上的每个属性,进行浅拷贝
for (let k in obj) {
newObj[k] = obj[k]
}
// 返回拷贝的结果
return newObj
}
一般情况下浅拷贝时是不需要拷贝原型上的属性的
for(... in ...) {} 会拷贝原型上的属性,此时需要增加一个判断, 通过 对象.hasOwnProperty('属性')方法判断, 如果当前属性是通过继承得来的,那么就不拷贝
对象/数组.hasOwnProperty('属性') :
返回一个布尔值
当返回值为true时, 表示当前属性是该 对象/数组 本身的属性,不是继承的属性
当返回值为false是时, 表示当前属性是 继承的属性
代码实现:
<script>
const o = {
name: 'zs',
info: {
city: '北京',
area: '顺义区'
}
}
o.__proto__ = {
a: 10,
b: 20
}
// 浅拷贝:只把对象上第一层的属性拷贝一份,放到一个新对象上!!!
function simpleCopy(obj) {
// 要判断用户传进来的 obj 是“数组”还是“真正的对象”
const newObj = Array.isArray(obj) ? [] : {}
// 循环对象上的每个属性,进行浅拷贝
for (let k in obj) {
if (obj.hasOwnProperty(k)) {
newObj[k] = obj[k]
}
}
// 返回拷贝的结果
return newObj
}
const o2 = simpleCopy(o)
console.log(o2)
</script>
详解:
for ...in ... 循环会循环到继承过来的属性
for (let k in o) {
// 调用 对象.hasOwnProperty() 方法,可以判断指定的属性是继承过来的,还是我本身就有
// 如果 hasOwnProperty() 返回值是 true,证明这个属性是自己的,不是继承的
// 如果 hasOwnProperty() 返回值是 false,证明这个属性是继承过来的
// o.hasOwnProperty('属性')
if (o.hasOwnProperty(k)) {
console.log(k, o[k])
}
}
如何简易高效的实现浅拷贝
实际开发中的方法:
1. Object.assign(要拷贝的, 被拷贝的)
2. 展开运算符 ...
方案一:
const o = {
name: 'zs',
info: {
city: '北京',
area: '顺义区'
}
}
const o2 = {}
// 实现对象浅拷贝的方法
Object.assign(o2, o)
console.log(o2.info === o.info)
const arr = [1, 2, { name: 'zs' }]
const arr2 = []
// Object.assign 可以对数组实现浅拷贝
Object.assign(arr2, arr)
console.log(arr2[2] === arr[2])
方案二:
const o = {
name: 'zs',
info: {
city: '北京',
area: '顺义区'
}
}
const o2 = {
// 展开运算符
...o
}
console.log(o2.info === o.info)
const arr = [1, 2, { name: 'zs' }]
const arr2 = [...arr]
console.log(arr2[2] === arr[2])
深拷贝
基于浅拷贝再做一次判断, 如果当前循环的值是对象类型, 那么再次调用方法, 这样就形成了递归
凡是遇到当前的值是对象类型就对当前的值再做一次浅拷贝
代码演示:
<script>
const o = {
name: 'zs',
info: {
city: '北京',
area: '顺义区'
}
}
// 深拷贝的方法
function deepCopy(obj) {
const newObj = Array.isArray(obj) ? [] : {}
for (let k in obj) {
if (obj.hasOwnProperty(k)) {
// 如果当前属性的值是对象类型,则需要进一步做浅拷贝的操作
if (typeof obj[k] === 'object') {
newObj[k] = deepCopy(obj[k])
} else {
newObj[k] = obj[k]
}
}
}
return newObj
}
const o2 = deepCopy(o)
console.log(o2.info === o.info)
</script>