js 拷贝问题

js 拷贝

  • js拷贝有浅拷贝和深拷贝。
  • 浅拷贝:只会将原始对象的属性复制到新对象中,如果原始对象包含引用对象属性,那么只会复制其引用。当原始对象引用对象属性改变,拷贝对象的引用属性也会跟着改变。

  • 深拷贝:创建一个对象,把原对象的所有属性都拷贝(包括引用类型)。并且无论怎么改变原对象的属性,新对象都不会发生变化

一、浅拷贝(引用对象属性只复制引用)

// 浅拷贝(只能拷贝对象的基本数据类型属性)
// 1、Object.assign (对象使用)
const obj = {
	name: '张三',
	age: '18'
}
const newObj = Object.assign({}, obj)
console.log(newObj) // { name: '张三', age: '李四' }

// 2、for in 循环 (对象、数组使用)
function shallowCopy(source){
	var target = source instanceof Array ? [] : {};
	for(var i in source){
		// 使用 hasOwnProperty 方法判断属性是否存在
	    if(source.hasOwnProperty(i)){
	        target[i]=source[i];
	    }
	}
	return target;
}

// 3、Array.prototype.slice() (数组使用)
const arr = [1, 2, 3, 4]
const newArr = arr.slice(0)
console.log(newArr) // (4) [1, 2, 3, 4]

// 4、Array.prototype.concat() (数组使用)
const arr2 = [1, 2, 3, 4]
const newArr2 = arr2.concat(arr2)
console.log(newArr2) // (4) [1, 2, 3, 4]

// 5、Array.concat() (数组使用)
const arr3 = [1, 2, 3, 4]
const newArr3 = Array.from(arr3)
console.log(newArr3) // (4) [1, 2, 3, 4]

二、深拷贝

// 深拷贝
// 1、JSON.parse() 和 JSON.stringify() (对象、数组使用)
/**
  JSON.parse() 和 JSON.stringify() 也算深拷贝,但是它不能处理函数、undefined、
  Symbol、Date等。对于大型数据结构,JSON.stringify() 和 JSON.parse() 可能非常慢,
  因为它们需要遍历整个对象并创建新的数据结构
  存在的坑:
  · 如果对象中有函数有方法就不能实现拷贝了
  · 会抛弃对象的constructor,所有的构造函数会指向Object
  · 对象有循环引用,会报错
*/

let objJson = { 
	name: 'aaa',
	age: 30, 
	action: function () {} 
}
const arrJson = [1, 2, 3, 4]
console.log(JSON.parse(JSON.stringify(objJson)))
console.log(JSON.parse(JSON.stringify(arrJson)))

// 2、使用递归
function deepCopy(obj, parent = null) {
    // 创建一个新对象
    let result = {}
    let keys = Object.keys(obj),
        key = null,
        temp= null,
        _parent = parent
    // 该字段有父级则需要追溯该字段的父级
    while (_parent) {
        // 如果该字段引用了它的父级则为循环引用
        if (_parent.originalParent === obj) {
            // 循环引用直接返回同级的新对象
            return _parent.currentParent
        }
        _parent = _parent.parent
    }
    for (let i = 0; i < keys.length; i++) {
        key = keys[i]
        temp= obj[key]
        // 如果字段的值也是一个对象
        if (temp && typeof temp=== 'object') {
            // 递归执行深拷贝 将同级的待拷贝对象与新对象传递给 parent 方便追溯循环引用
            result[key] = deepCopy(temp, {
                originalParent: obj,
                currentParent: result,
                parent: parent
            });
        } else {
            result[key] = temp
        }
    }
    return result
}

const obj1 = {
    x: 1, 
    y: 2
}
obj1.z = obj1

var obj2 = deepCopy(obj1)
console.log(obj1) //太长了去浏览器试一下吧~ 
console.log(obj2) //太长了去浏览器试一下吧~ 
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值