摘要:但是進行的是淺拷貝,拷貝的是屬性值。對象展開符深拷貝的實現方式手動復制轉成再轉回來只有可以轉成格式的對象才可以這樣用,像沒辦法轉成沒被改到使用方法避免相互引用對象導致死循環,如的情況四參考關于的淺拷貝和深拷貝
一、理解
淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存。但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象。二、淺拷貝與深拷貝
淺拷貝:賦值時,基本數據類型按值傳遞,對象按引用傳遞
var a = 25; var b = a; b = 18; console.log(a);//25 console.log(b);//18 // b的修改并不會影響到a,因為它們是基本類型數據
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = obj1; obj2.b = 100; console.log(obj1); // { a: 10, b: 100, c: 30 } <-- b 被改到了 console.log(obj2); // { a: 10, b: 100, c: 30 } // obj2修改了b的值,同時obj1的b也會被修改,因為他們根本是同一個對象,這就是所謂的淺拷貝
深拷貝:
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 } <-- b 沒被改到 console.log(obj2); // { a: 10, b: 100, c: 30 }三、實現方式
淺拷貝的實現方式
(1)直接賦值,就是淺拷貝。對象直接復制,則新對象的改變也會修改到舊對象。
(2) Object.assign(target, ...sources)
Object.assign是ES6的新函數。Object.assign()方法可以把任意多個的源對象自身的可枚舉屬性拷貝給目標對象,然后返回目標對象。但是Object.assign()進行的是淺拷貝,拷貝的是屬性值。假如源對象的屬性值是一個指向對象的引用,它也只拷貝那個引用值。
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
(3)對象展開符...
var obj = [{index: 1, msg: "one"}, {index: 2, msg: "two"}]; var obj2 = [...obj]; console.log(obj2); //[{index: 1, msg: "one"}, {index: 2, msg: "two"}] obj2.push({index: 3, msg: "three"}); console.log(obj2); // [{index: 1, msg: "one"}, {index: 2, msg: "two"}, {index: 3, msg: "three"}] console.log(obj); // [{index: 1, msg: "one"}, {index: 2, msg: "two"}] obj2[1].msg = "two again"; console.log(obj2); // [{index: 1, msg: "one"}, {index: 2, msg: "two again"}, {index: 3, msg: "three"}] console.log(obj); // [{index: 1, msg: "one"}, {index: 2, msg: "two again"}]
深拷貝的實現方式
(1)手動復制
var obj1 = { a: 10, b: 20, c: 30 }; var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
(2)轉成JSON再轉回來(只有可以轉成JSON格式的對象才可以這樣用,像function沒辦法轉成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
(3)使用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; } var str = {}; var obj = { a: {a: "hello", b: 21} }; deepClone(obj, str);四、參考
【1】關于JavaScript的淺拷貝和深拷貝
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100164.html
摘要:在中可以通過添加一個參數來實現遞歸,調用就可以實現一個深拷貝。利用序列化實現一個深拷貝 在JavaScript中,對于Object和Array這類引用類型值,當從一個變量向另一個變量復制引用類型值時,這個值的副本其實是一個指針,兩個變量指向同一個堆對象,改變其中一個變量,另一個也會受到影響。 這種拷貝分為兩種情況:拷貝引用和拷貝實例,也就是我們說的淺拷貝和深拷貝 淺拷貝(shallow...
摘要:引用類型值引用類型值是保存在堆內存中的對象,變量保存的只是指向該內存的地址,在復制引用類型值的時候,其實只復制了指向該內存的地址。 前言 要理解 JavaScript中淺拷貝和深拷貝的區別,首先要明白JavaScript的數據類型。JavaScript有兩種數據類型,基礎數據類型和引用數據類型。js的基本類型:undefined,null,string,boolean,number,s...
摘要:說明外層數組拷貝的是實例說明元素拷貝是引用深拷貝在堆中重新分配內存,并且把源對象所有屬性都進行新建拷貝,拷貝后的對象與原來的對象完全隔離,互不影響。中的方法可以實現深拷貝,源碼原理也是遞歸使用淺拷貝。 1.淺拷貝 當把數組或對象簡單賦值給其他變量的時候,實際上進行的是淺拷貝,淺拷貝是拷貝引用,只是將拷貝后的引用指向同一個對象實例,彼此間的操作還會互相影響。 分為兩種情況:直接拷貝源對象...
摘要:而大多數實際項目中,我們想要的結果是兩個變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區別淺拷貝只復制一層對象的屬性,而深拷貝則遞歸復制了所有層級。 為什么會用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
摘要:而大多數實際項目中,我們想要的結果是兩個變量初始值相同互不影響。所以就要使用到拷貝分為深淺兩種深淺拷貝的區別淺拷貝只復制一層對象的屬性,而深拷貝則遞歸復制了所有層級。 為什么會用到淺拷貝和深拷貝 首先來看一下如下代碼 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...
閱讀 2557·2023-04-25 20:05
閱讀 2886·2023-04-25 17:56
閱讀 2195·2021-10-14 09:49
閱讀 2681·2019-08-29 15:10
閱讀 2922·2019-08-29 12:25
閱讀 416·2019-08-28 18:23
閱讀 757·2019-08-26 13:26
閱讀 1370·2019-08-23 18:21