摘要:深拷貝和淺拷貝深拷貝和淺拷貝的示意圖大致如下淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。參考文章什么是深拷貝和淺拷貝及其實現方式
走在前端的大道上
本篇將自己讀過的相關文章中,對自己有啟發的章節片段總結在這(會對原文進行刪改),會不斷豐富提煉總結更新。
淺拷貝var m = { a: 10, b: 20 } var n = m; n.a = 15; // 這時m.a的值是多少
m.a會輸出15,因為這是淺拷貝,n和m指向的是同一個堆,對象復制只是復制的對象的引用。
深拷貝深拷貝和上面淺拷貝不同,就是徹底copy一個對象,而不是copy對象的引用,例如,還是之前的例子,我們這么寫:
var m = { a: 10, b: 20 } var n = {a:m.a,b:m.b}; n.a = 15;
這次,我們再來輸出m.a ,發現m.a的值還是10,并沒有改變,m對象和n對象是雖然所有的值都是一樣的,但是在堆里面,對應的不是同一個了,這個就是深拷貝。
深拷貝和淺拷貝深拷貝和淺拷貝的示意圖大致如下:
淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。
淺拷貝的實現方式 1、可以通過簡單的賦值實現類似上面的例子,當然,我們也可以封裝一個簡單的函數,如下:
function simpleClone(initalObj) { var obj = {}; for ( var i in initalObj) { obj[i] = initalObj[i]; } return obj; } var obj = { a: "hello", b:{ a: "world", b: 21 }, c:["Bob", "Tom", "Jenny"], d:function() { alert("hello world"); } } var cloneObj = simpleClone(obj); console.log(cloneObj.b); console.log(cloneObj.c); console.log(cloneObj.d); cloneObj.b.a = "changed"; cloneObj.c = [1, 2, 3]; cloneObj.d = function() { alert("changed"); }; console.log(obj.b); console.log(obj.c); console.log(obj.d);2、Object.assign()實現
Object.assign() 方法可以把任意多個的源對象自身的可枚舉屬性拷貝給目標對象,然后返回目標對象。但是 Object.assign() 進行的是淺拷貝,拷貝的是對象的屬性的引用,而不是對象本身。
var obj = { a: {a: "hello", b: 21} ,c: 33}; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed" initalObj.c = 66; console.log(obj.c); // 33
注意:當object只有一層的時候,是深拷貝,例如如下:
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 }深拷貝的實現方式
1、方法一還是手動復制
和上面的舉例一樣,手動復制可以實現深拷貝。
2、對象只有一層的話可以使用上面的:Object.assign()函數
3、轉成 JSON 再轉回來
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
用JSON.stringify把對象轉成字符串,再用JSON.parse把字符串轉成新的對象。
可以封裝如下函數
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; };
4、遞歸拷貝
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);
5、使用Object.create()方法
直接使用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; }
6、jquery
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
7、lodash
另外一個很熱門的函數庫lodash,也有提供_.cloneDeep用來做 Deep Copy。
var _ = require("lodash"); var obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; var obj2 = _.cloneDeep(obj1); console.log(obj1.b.f === obj2.b.f); // false
這個性能還不錯,使用起來也很簡單。
參考文章:
1.什么是js深拷貝和淺拷貝及其實現方式
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/90798.html
摘要:本文解釋中深拷貝和淺拷貝的區別。深拷貝深拷貝指遞歸的復制對象的屬性給新對象。有些時候一層的深拷貝被認為是淺拷貝,比如的值是一個對象,淺拷貝出來的新對象直接引用了原對象的對象,所以也會相互影響的。 本文解釋javascript中深拷貝和淺拷貝的區別。 淺拷貝/Shallow Copy 淺拷貝指拷貝了引用值。 var original = {prop1 : Prop1, prop2 : p...
摘要:接下來就讓我們更細致的探究中的深淺拷貝。總結以上對深拷貝和淺拷貝做了簡單的介紹,在深拷貝的實現上也只介紹了最簡單的實現形式,并未考慮復雜情況以及相應優化,想要對深拷貝有更深入的了解,需要大家花時間去深入研究,或者可以關注我后續文章的動態。 對象和數組的拷貝對我來說一直都是一個比較模糊的概念,一直有點一知半解,但是在實際工作中又偶爾會涉及到,有時候還會一不小心掉坑里,不知道大家有沒有同樣...
摘要:深拷貝和淺拷貝的區別背景最近在用框架寫頁面,賦值給中的對象時會出現一個問題,賦值和被賦值對象之中任何一個有變化,另一個也會隨之變化。 深拷貝和淺拷貝的區別 背景:最近在用vue框架寫頁面,賦值給Vue.$data中的對象時會出現一個問題,賦值和被賦值對象之中任何一個有變化,另一個也會隨之變化。例如: var b = { foo: 123 }; var vm = new Vue(...
摘要:參考鏈接淺拷貝最簡單的淺拷貝就賦值。所謂的淺拷貝就是,后面的對象和前面的對象在第一層數據結構中指向同一個堆地址。但是如果前面的數據不止有一層,如此時,使用和方式實現的都是淺拷貝。深拷貝管你怎么變,互不影響。 參考鏈接:http://www.cnblogs.com/st-les...https://blog.csdn.net/hj7jay/... 淺拷貝: 1.最簡單的淺拷貝就賦值。由于...
閱讀 3544·2021-11-23 10:10
閱讀 3318·2019-08-30 14:03
閱讀 2072·2019-08-30 13:09
閱讀 3400·2019-08-29 15:29
閱讀 1548·2019-08-29 11:23
閱讀 2014·2019-08-28 18:28
閱讀 2849·2019-08-26 13:34
閱讀 2174·2019-08-26 11:32