今天看es6的時候忽然想到一個問題就是針對於js的深拷貝和淺拷貝的問題,其實說直接點那,就是深複製和淺複製只針對像 Object, Array 這樣的複雜對象的。簡單來說,淺複製只複製一層對象的屬性,而深複製則遞歸複製了所有層級。
因爲淺複製只會將對象的各個屬性進行依次複製,並不會進行遞歸複製,而
JavaScript 存儲對象都是存地址的,所以淺複製會導致 obj.arr 和 shadowObj.arr 指向同一塊內存地址,大概的示意圖如下。
舉一個列子哈:
let obj = { a:11, b: [22,33] }; function objCopy(src) { let dst = {}; for (let prop in src) { if (src.hasOwnProperty(prop)) { dst[prop] = src[prop]; } } return dst; } let _copy = objCopy(obj);
因爲淺複製只會將對象的各個屬性進行依次複製,並不會進行遞歸複製,而 JavaScript 存儲對象都是存地址的,所以淺複製會導致 obj.b和
_copy.b 指向同一塊內存地址,大概的示意圖如下。
導致的結果就是這樣:
_copy.arr[1] = 88; obj.b[1] // = 88
而深複製則不同,它不僅將原對象的各個屬性逐個複製出去,而且將原對象各個屬性所包含的對象也依次採用深複製的方法遞歸複製到新對象上。這就不會存在上面 obj 和 _copy的 b屬性指向同一個對象的問題。
深拷貝要實現的效果是這樣的:
實現深拷貝的方法如下
最簡單的深拷貝,拿好:
b = JSON.parse( JSON.stringify(a) )
不過這有侷限性:
- 無法複製函數
- 原型鏈沒了,對象就是object,所屬的類沒了。
但是簡單,大多時候完全可以滿足需求了
jQuery.extend(true, { a : { a : "a" } }, { a : { b : "b" } } );
jQuery.extend( { a : { a : "a" } }, { a : { b : "b" } } );
(數組深拷貝)
var arr = ["One","Two","Three"]; var arrtoo = arr.slice(0); arrtoo[1] = "middle"; document.writeln("數組的原始值:" + arr + "<br />");//Export:數組的原始值:One,Two,Three document.writeln("數組的新值:" + arrtoo + "<br />");//Export:數組的新值:One,middle,Three
concat() 方法用於連接兩個或多個數組。
該方法不會改變現有的數組,而僅僅會返回被連接數組的一個副本。
語法
arrayObject.concat(arrayX,arrayX,......,arrayX)
說明
返回一個新的數組。該數組是通過把所有 arrayX 參數添加到 arrayObject 中生成的。如果要進行 concat() 操作的參數是數組,那麼添加的是數組中的元素,而不是數組。
(對象深拷貝)
就是把對象的屬性遍歷一遍,賦給一個新的對象。
var deepCopy= function(source) { var result={};
for (var key in source) {
result[key] = typeof source[key]===’object’? deepCoyp(source[key]): source[key];
}
return result;
}
var cloneObj = function(obj){
var str, newobj = obj.constructor === Array ? [] : {};
if(typeof obj !== 'object'){
return;
} else if(window.JSON){
str = JSON.stringify(obj), //系列化對象
newobj = JSON.parse(str); //還原
} else {
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ?
cloneObj(obj[i]) : obj[i];
}
}
return newobj;
};
這個函數可以深拷貝 對象和數組
小弟水平有限,大神勿噴,理解不對的地方請批評指正。謝謝~~