js 对象克隆方法总结(不改变原对象)

时间:2023-11-24 08:56:14

1.通用对象克隆:

function clone(obj){
let temp = null;
if(obj instanceof Array){
temp = obj.concat();
}else if(obj instanceof Function){
//函数是共享的是无所谓的,js也没有什么办法可以在定义后再修改函数内容
temp = obj;
}else{
temp = new Object();
for(let item in obj){
let val = obj[item];
temp[item] = typeof val == 'object'?clone(val):val; //这里也没有判断是否为函数,因为对于函数,我们将它和一般值一样处理
}
}
return temp;
}

整个clone函数的思路可能有点乱,但是可以这样理顺:

把obj的value当做只有普通值、数组和函数,先按部就班地处理,然后再考虑之前的“普通值”有可能是object,所以这里做个判断,在递归一下clone函数就可以了

换用toSting()方法克隆:
思路:
  //1.遍历对象              for(var prop in obj)
  //2.判断要复制的属性是否是原始值    typeof(obj[prop])
  //3.判断要复制的属性是数组还是对象   toString(建议使用)   instanceof   constructor
  //4.创建对应的数组和对象
instanceof:  a instanceof b  判断对象a是否在构造函数b的原型链上
  function deepClone(origin, target) {
    var target = target || {};
    toStr = Object.prototype.toString, //对象调用toSting()
    arrStr = "[obect Array];"
    for(var prop in origin) {
    if(origin.hasOwnProperty(prop)) { //判断是否是原型上的属性还是自己的属性
      if(origin[prop] !== "null" && typeof(origin[prop]) == "object") { //判断是数组还是对象且复制者不能为空
        if(toStr.call(origin[prop]) == arrStr) {
          target[prop] = [];
        } else {
          target[prop] = {};
        }
          deepClone(origin[prop], target[prop]);
        } else {
          target[prop] = origin[prop];  //递归调用
        }
      }
    }
    return target;
  }

ps:值得注意的是,官方有一种方法可以生成新的函数实例,就是bind()

function aaa(){
console.log(this);
}; var c = aaa;
var d = aaa.bind(); //bind如果不传东西,默认是window对象 c === aaa; //true
d === aaa; //false

2.JSON对象序列化方法

这个方法明显是简单得多,但是有个弊端,就是不能复制函数

var obj = {a:1,b:2}
var newObj = JSON.parse(JSON.stringify(obj));
obj.c = 3;
console.log(obj,newObj);

3.dom元素的复制——cloneNode

<div id="box"></div>
let div = document.getElementById('box');
let box2 = div.cloneNode(true);
console.log(div,box2);

4.es6新方法——Object.assign

//比较常用
var obj = {a:1,b:2}
var newObj = Object.assign({}, obj);
obj.c = 3;
console.log(obj,newObj);

5.es6新方法——扩展运算符(...)

var obj = {a:1,b:2}
var newObj ={...obj}
obj.c = 3;
console.log(obj,newObj);