本篇文章帶給大家的內容是關於js中淺拷貝與深拷貝的實作方式有哪些? (總結),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
js有五種基本資料類型,string,number,boolean,null,undefind。這五種類型的賦值,就是值傳遞。物件的賦值是將物件位址的引用賦值。這時候修改物件中的屬性或值,會導致所以引用這個物件的值改變。如果想要真的複製一個新的對象,而不是複製對象的引用,就要用到對象的深拷貝。
不多說,最基礎的賦值方式,只是將物件的引用賦值。
Object.assign是ES6的新函數。 Object.assign() 方法可以把任意多個的來源物件自身的可枚舉屬性拷貝給目標對象,然後返回目標對象。但是 Object.assign() 進行的是淺拷貝,拷貝的是物件的屬性的引用,而不是物件本身。
Object.assign(target, ...sources)
參數:
target:目標物件。
sources:任意多個來源物件。
傳回值:目標物件會被傳回。
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
要注意的是:
Object.assign()可以處理一層的深度拷貝,如下:
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = Object.assign({}, obj1); obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } <-- 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c }; obj2.b = 100; console.log(obj1); // { a: 10, b: 20, c: 30 } <-- 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }
用JSON.stringify把物件轉成字串,再用JSON.parse把字串轉成新的物件。
var obj1 = { body: { a: 10 } }; var obj2 = JSON.parse(JSON.stringify(obj1)); obj2.body.a = 20; console.log(obj1); // { body: { a: 10 } } <-- 沒被改到 console.log(obj2); // { body: { a: 20 } } console.log(obj1 === obj2); // false console.log(obj1.body === obj2.body); // false
這樣做是真正的Deep Copy,這種方法簡單易用。
但是這種方法也有不少壞處,譬如它會拋棄對象的constructor。也就是深拷貝之後,不管這個物件原來的建構子是什麼,在深拷貝之後都會變成Object。
這種方法能正確處理的物件只有 Number, String, Boolean, Array, 扁平對象,也就是那些能夠被 json 直接表示的資料結構。 RegExp物件是無法以這種方式深拷貝。
也就是說,只有可以轉換成JSON格式的物件才可以這樣用,像function沒辦法轉換成JSON。
var obj1 = { fun: function(){ console.log(123) } }; var obj2 = JSON.parse(JSON.stringify(obj1)); console.log(typeof obj1.fun); // 'function' console.log(typeof obj2.fun); // 'undefined' <-- 没复制
function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : {}; arguments.callee(prop, obj[i]); } else { obj[i] = prop; } } return obj; } var str = {}; var obj = { a: {a: "hello", b: 21} }; deepClone(obj, str); console.log(str.a);
直接使用var newObj = Object.create(oldObj),可以達到深拷貝的效果。
function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : Object.create(prop); } else { obj[i] = prop; } } return obj; }
jquery 有提供一個$.extend可以用來做 Deep Copy。
var $ = require('jquery'); var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; var obj2 = $.extend(true, {}, obj1); console.log(obj1.b.f === obj2.b.f); // false
還有一些其它的第三方函式庫有深拷貝function,如lodash。
#以上是js中淺拷貝與深拷貝的實作方式有哪些? (總結)的詳細內容。更多資訊請關注PHP中文網其他相關文章!