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);