在js中將一個值a賦值給另外一個值b,在什麼狀況下改變了b的值會影響a的值?在知道哪一種類型賦值後改變值會影響原對象的狀況下該怎麼作纔不會影響原對象?就是這裏須要討論的問題。
首先是哪一種類型賦值後改變賦值後的值會影響到被賦值的值?java
let a = 1; let b = a; b = 2; console.log(a) // 1 let obj = {a: 1} let obj2 = obj; obj2.a = 2; console.log(obj) // {a: 2}
從這裏咱們能夠知道:簡單數據類型的number賦值後就算改變賦值後的值也不會影響到其自己,可是對象複製後改變了賦值後的值就會影響到其自己。es6
javaScript中的數據類型分爲兩類,簡單數據類型和複雜數據類型;
1.簡單數據類型:包括數值,字符串、布爾值、null、undefined;
2.複雜數據類型:對象即屬性的集合(function、Array、Object);數組
先了解數據類型在計算機中的存儲;
1.簡單數據類型:存儲的是對象的原始數據;
2.複雜數據類型:對象的原型也是引用類型,對象類型的值單獨存放。對象原型的方法和屬性放在內存中,經過原型鏈的方式來指向這個地址;因此對象類型存儲的是對象的引用地址;數據結構
對象類型在複製的時候,只是將對象的引用複製了,將a對象的引用地址值賦值給了b
因此在b改變對象屬性值的時候,a的引用也發生了改變,它們在內存中獲取的都是同一個對象;函數
若是想要複製一個複雜數據類型卻不想影響原對象,此時就須要用到深拷貝/淺拷貝。code
淺拷貝:
首先由一個數組[1,2,3]或對象{name:'porco', age:1},這樣的數組或對象中的值統一不爲[數組array]或[對象obj]的只有一層數據結構的簡單對象,被稱爲淺拷貝對象,若是單純的賦值使用例如let a = [1,2,3],若是改變了a,那麼原數組也會相應的被改變,對象也是同樣。因此遇到這種狀況,想要複製的對象的改變不想影響到原對象,就須要淺拷貝方法:以下對象
/** * 淺拷貝對象: **/ let obj = {a:1,b:2} let obj2 = {}; /*方法1*/ for(let e in obj) { obj2[e] = obj[e] } /*方法2*/ Object.keys(obj).forEach(e => { obj2[e] = obj[e] }) obj2.a = 0; console.log(obj2) //{a:0, b:2} console.log(obj) //{a:1, b:2} /*這裏還可使用兩種es6淺拷貝方式*/ /*這是直接淺拷貝:*/ let obj2 = Object.assign({}, obj); /*以及直接使用拓展運算符拷貝*/ let obj2 = {...obj} /*以上四種方式都可做爲淺拷貝對象的方式*/ /***********************************/ /** * 淺拷貝數組: **/ let arr = [1,2,3] /*第一種淺拷貝數組方式*/ let arr2 = arr.slice(); /*第二種淺拷貝數組方式*/ let arr2 = arr.concat(); /*第三種淺拷貝數組方式*/ let arr2 = []; arr.forEach(e => { arr2.push(e) }) arr2.[0] = 0; console.log(arr2) //[0,2,3] console.log(arr) //[1,2,3]
深拷貝:
當對象中的第一層級有一項是數組或對象,淺拷貝失效,例如:let a = [{a:1}]或let a = {a:{aa:1}},這樣,使用上面的方法都會失效。這時必須使用深拷貝
一、最簡單的辦法遞歸
let BBB = JSON.parse(JSON.stringify(AAA))
這種方法簡單適用於普通場景,可是也會拋棄對象的constructor,無論以前的構造函數什麼樣,深拷貝後都會變成object.這種方法能正確處理的對象只有 Number, String, Boolean, Array, 而且能用jso格式直接表示的數據結構。ip
二、一個遞歸方法:內存
function deepClone(obj) { let objClone = Array.isArray(obj) ? [] : {}; if(obj && typeof obj === "object") { for(let key in obj) { if(obj.hasOwnProperty(key)) { if(obj[key] && typeof obj[key] === "object") { objClone[key] = deepClone(obj[key]); } else { objClone[key] = obj[key]; } } } } return objClone }
以上就是討論了哪些值類型賦值不須要使用拷貝,哪些值類型賦值須要淺拷貝,哪些值類型賦值須要深拷貝