淺談深拷貝與淺拷貝?深拷貝幾種方法。
深拷貝和淺拷貝的區別?
如何區分深拷貝與淺拷貝,大白話來說,就是假設B複製了A,當修改A時,看B是否會發生變化,如果B也跟著變了,說明這是淺拷貝,拿人手短,如果B沒變,那就是深拷貝,自食其力。
先看一個例子:
let a = [0, 1, 2, 3, 4], b = a; console.log(a === b); // true a[0] = 9; console.log(a, b); // [9, 1, 2, 3, 4]
吆哈,明明b複製了a,為啥修改陣列a,陣列b也跟著變了??
基本資料型別和複雜(引用)資料型別?
基本資料型別:number, string, boolean, null, undefined, symbol
引用資料型別:Object類,有常規名值對的無須物件{a: 1}, 陣列[1, 2, 3],函式等。
而這兩類資料儲存方式分別是這樣的:
1. 基本型別–名值儲存在棧記憶體中,例如let a=1;
當你b=a複製時,棧記憶體會新開闢一個記憶體,例如這樣:
所以當你此時修改a=2,對b並不會造成影響,因為此時的b已自食其力,翅膀硬了,不受a的影響了。當然,let a=1, b=a; 雖然b不受a影響,但這也算不上深拷貝,因為深拷貝本身只針對較為複雜的object型別資料。
2.引用資料型別–名存在棧記憶體中,值存在於堆記憶體中,但是棧記憶體會提供一個引用的地址指向堆記憶體中的值,我們以上面淺拷貝的例子畫個圖:
當b=a進行拷貝時,其實複製的是a的引用地址,而並非堆裡面的值。
而當我們a[0]=1時進行陣列修改時,由於a與b指向的是同一個地址,所以自然b也受了影響,這就是所謂的淺拷貝了。
那,要是在堆記憶體中也開闢一個新的記憶體專門為b存放值,就像基本型別那樣,豈不就達到深拷貝的效果了。
實現簡單的深拷貝方法?
先看幾個簡單例子?
1.slice() 方法
// 先看一個js中的方法slice() 方法可從已有的陣列中返回選定的元素。 // 該方法並不會修改陣列,而是返回一個子陣列。arrayObject.slice(start,end) let a1 = [1, 2, 3, 4], b2 = a1.slice(); a1[0] = 2; console.log(a1, b2);
如上圖所述,slice()方法看似是一個深拷貝的方法了!在改造一下上述程式碼片段,我們再看 ?
let a1 = [1, 2, [5,6], 3, 4], b2 = a1.slice(); a1[0] = 2; a1[2][0] = 9; console.log(a1, b2);
拷貝的不徹底,b物件的一級屬性確實不受影響了,但是二級屬性還是沒能拷貝成功,仍然脫離不了a的控制,說明slice根本不是真正的深拷貝。
2.遞迴
// 簡單深拷貝封裝遞迴函式 function deepClone(obj) { let objClone = Array.isArray(obj) ? [] : {}; if (obj && typeof obj === "object") { for (key in obj) { if (obj.hasOwnProperty(key)) { // 注:hasOwnProperty()方法 //判斷obj子元素是否為物件,如果是,遞迴複製 console.log(obj[key]) if (obj[key] && typeof obj[key] === "object") { objClone[key] = deepClone(obj[key]); } else { //如果不是,簡單複製 objClone[key] = obj[key]; } } } } return objClone; } let arr = [1, 2, [5, 6], 4], b1 = deepClone(arr); arr[2][0] = 9; console.log(arr, b1); // 跟之前想象的一樣,現在b脫離了a的控制,不再受a影響了。這裡再次強調,深拷貝,是拷貝物件各個層級的屬性。
注:hasOwnProperty() 官方 MDN講解方法會返回一個布林值,指示物件自身屬性中是否具有指定的屬性(也就是,是否有指定的鍵)。
3. 除了遞迴,我們還可以借用JSON物件的parse和stringify。
function deepClone(obj){ let _obj = JSON.stringify(obj), objClone = JSON.parse(_obj); return objClone } let a=[0,1,[2,3],4], b=deepClone(a); a[0]=1; a[2][0]=1; console.log(a,b);
4. 除了上面兩種方法之外,我們還可以借用JQ的extend方法。
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷貝,為true為深拷貝,為false,則為淺拷貝
target Object型別 目標物件,其他物件的成員屬性將被附加到該物件上。
object1 objectN可選。 Object型別 第一個以及第N個被合併的物件。
let a=[0,1,[2,3],4], b=$.extend(true,[],a); a[0]=1; a[2][0]=1; console.log(a,b);
原文連結: https://blog.csdn.net/qq_43531694/article/details/102586168
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946034/viewspace-2660396/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【JS】深拷貝與淺拷貝,實現深拷貝的幾種方法JS
- JS深拷貝與淺拷貝JS
- vue深拷貝淺拷貝Vue
- 深入淺出深拷貝與淺拷貝
- 深拷貝、淺拷貝與Cloneable介面
- 賦值、淺拷貝與深拷貝賦值
- Python淺拷貝與深拷貝Python
- python深拷貝與淺拷貝Python
- React之淺拷貝與深拷貝React
- 物件的深拷貝與淺拷貝物件
- 【c++】淺拷貝與深拷貝C++
- iOS深拷貝和淺拷貝iOS
- Java深拷貝和淺拷貝Java
- 物件深拷貝和淺拷貝物件
- javascript 淺拷貝VS深拷貝JavaScript
- JavaScript深拷貝和淺拷貝JavaScript
- js 淺拷貝和深拷貝JS
- js 深拷貝和淺拷貝JS
- JavaScript淺拷貝和深拷貝JavaScript
- js深拷貝和淺拷貝JS
- js 深拷貝 vs 淺拷貝JS
- 深入淺出的“深拷貝與淺拷貝”
- [JS系列二]談談深拷貝和淺拷貝,如何實現深拷貝JS
- 淺談Java中的淺拷貝和深拷貝Java
- java深克隆(深拷貝)和淺克隆(淺拷貝)Java
- 淺探js深拷貝和淺拷貝JS
- JavaScript中的淺拷貝與深拷貝JavaScript
- 淺拷貝與深拷貝的實現
- 【JavaScript】物件的淺拷貝與深拷貝JavaScript物件
- 淺拷貝與深拷貝程式碼(javascript)JavaScript
- Python3之淺談----深拷貝與淺拷貝Python
- JS中的深淺拷貝以及實現深拷貝的幾種方法.JS
- C++淺拷貝和深拷貝C++
- 實現物件淺拷貝、深拷貝物件
- go slice深拷貝和淺拷貝Go
- JavaScript之深拷貝和淺拷貝JavaScript
- js的深拷貝和淺拷貝JS
- 聊聊物件深拷貝和淺拷貝物件