---針對(duì)引用類型
傳統(tǒng)復(fù)制 將兩個(gè)變量都指向了同一塊內(nèi)存空間,A變動(dòng)B也會(huì)隨之變動(dòng);
JavaScript let arr1 = [ "a", "b", { name:"cc" } ] let arr2 = arr1 arr1.push("d"); console.log(arr1); //[ 'a', 'b', { name: 'cc' }, 'd' ] console.log(arr2); //[ 'a', 'b', { name: 'cc' }, 'd' ]
拷貝:在賦值的時(shí)候即使目標(biāo)是引用類型,也在內(nèi)存中新開(kāi)辟一塊空間,將原始數(shù)據(jù)原封不動(dòng)的拷貝過(guò)去,從而修改A的時(shí)候不會(huì)影響到B。
淺拷貝
- 淺層次地拷貝,A中的變動(dòng)不會(huì)影響到B,但是如果A中存在引用類型,則二者存儲(chǔ)的都是引用類型的指針地址,如果變動(dòng),則會(huì)導(dǎo)致B也隨之變動(dòng),所以,這是淺拷貝。 (創(chuàng)建一個(gè)新對(duì)象,這個(gè)對(duì)象有著原始對(duì)象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果屬性是引用類型,拷貝的就是內(nèi)存地址,所以如果其中一個(gè)對(duì)象改變了這個(gè)地址,就會(huì)影響到另一個(gè)對(duì)象。)
JavaScript function shallowCopy(obj1, obj2){ for(var key in obj1){ obj2[key] = obj1[key]; } } let obj1 = { a:"a", b:"b", c:{ name:"cc" } } let obj2 = {} shallowCopy(obj1,obj2) obj2.d = "d"; //obj2的變動(dòng)對(duì)obj1沒(méi)有影響 obj2.c.name="hhh"; //obj2的變動(dòng)對(duì)obj1有了影響 console.log(obj1) //{ a: 'a', b: 'b', c: { name: 'hhh' } } console.log(obj2) //{ a: 'a', b: 'b', c: { name: 'hhh' }, d: 'd' } - 方法
- 數(shù)組
- Array.concat()
JavaScript let arr = ['a', 'b', 'c',{name:'dd'}]; let newArr = arr.concat(); newArr.push("e"); newArr[3].name = "hhh" console.log(arr); //[ 'a', 'b', 'c', { name: 'hhh' } ] console.log(newArr); //[ 'a', 'b', 'c', { name: 'hhh' }, 'e' ] - Array.slice()
JavaScript let arr = ["a", "b", "c"]; let newArr = arr.slice(); newArr.push("d"); console.log(arr); //[ 'a', 'b', 'c' ] console.log(newArr); //[ 'a', 'b', 'c', 'd' ]
- 對(duì)象
- Object.assign() 可以把任意多個(gè)源對(duì)象自身的可枚舉屬性拷貝給目標(biāo)對(duì)象,然后返回目標(biāo)對(duì)象
JavaScript let arr = { a:"aa", b:"bb", c:{name:"cc"} }; let newArr = Object.assign({}, arr) newArr.d = "dd"; newArr.c.name = "hhh"; console.log(arr); //{ a: 'aa', b: 'bb', c: { name: 'hhh' } } console.log(newArr); //{ a: 'aa', b: 'bb', c: { name: 'hhh' }, d: 'dd' } - ES6擴(kuò)展符{...Object}
JavaScript let arr = { a:"aa", b:"bb", c:{name:"cc"} }; let newArr = {...arr} newArr.d = "dd"; newArr.c.name = "hhh"; console.log(arr); //{ a: 'aa', b: 'bb', c: { name: 'hhh' } } console.log(newArr); //{ a: 'aa', b: 'bb', c: { name: 'hhh' }, d: 'dd' }
- 封裝淺拷貝 (遍歷需要克隆的對(duì)象,然后把需要克隆對(duì)象的屬性和屬性值都依次放在一個(gè)新的對(duì)象中,返回。)
JavaScript let shallowCopy = function(obj){ if(typeof obj !== "object") return; let newObj = obj instanceof Array? []:{}; for(let key in obj){ if(obj.hasOwnProperty(key)){ newObj[key] = obj[key]; } } return newObj; }
深拷貝
- 深層次地拷貝,A中的無(wú)論什么變動(dòng)都不會(huì)影響到B。深拷貝將數(shù)據(jù)完全復(fù)制到新開(kāi)辟的內(nèi)存空間中。(將一個(gè)對(duì)象從內(nèi)存中完整的拷貝一份出來(lái),從堆內(nèi)存中開(kāi)辟一個(gè)新的區(qū)域存放新對(duì)象,且修改新對(duì)象不會(huì)影響原對(duì)象。)
JavaScript function deepCopy(obj){ let newObj = Array.isArray(obj)? []:{}; if(obj && typeof obj === 'object'){ for(key in obj){ if(obj[key] && typeof obj[key] === "object"){ newObj[key] = deepCopy(obj[key]) }else{ newObj[key] = obj[key] } } } return newObj; } let obj1 = { a:"a", b:"b", c:{ name:"cc" } } let obj2 = deepCopy(obj1); obj2.c.name = "hhh"; obj2.d = "dd"; console.log(obj1); //{ a: 'a', b: 'b', c: { name: 'cc' } } console.log(obj2); //{ a: 'a', b: 'b', c: { name: 'hhh' }, d: 'dd' } - 方法
- 1.JSON.parse(JSON.stringify());
JavaScript let arr = { a:"a", b:"b", c:{ name:"cc" } }; let newArr = JSON.parse(JSON.stringify(arr)); newArr.c.name = "hhh"; console.log(arr); //{ a: 'a', b: 'b', c: { name: 'cc' } } console.log(newArr); //{ a: 'a', b: 'b', c: { name: 'hhh' } } - 2.遞歸[如果是原始類型,無(wú)需繼續(xù)拷貝,直接返回;如果是引用類型,創(chuàng)建一個(gè)新的對(duì)象,遍歷需要克隆的對(duì)象,將需要克隆對(duì)象的屬性執(zhí)行深拷貝后依次添加到新對(duì)象上]
JavaScript function clone(target) { if (typeof target === 'object') { let cloneTarget = {}; for (const key in target) { cloneTarget[key] = clone(target[key]); } return cloneTarget; } else { return target; } }; module.exports = function clone(target) { if (typeof target === 'object') { let cloneTarget = Array.isArray(target) ? [] : {}; for (const key in target) { cloneTarget[key] = clone(target[key]); } return cloneTarget; } else { return target; } }; ```
* 封裝深拷貝(判斷一下屬性值的類型,如果是對(duì)象,遞歸調(diào)用深拷貝函數(shù))
```JavaScript let deepCopy = function(obj){ //只拷貝對(duì)象 if(typeof obj !== "object") return; //根據(jù)obj的類型判斷是新建一個(gè)數(shù)組還是對(duì)象 let newObj = obj instanceof Array? []:{}; //遍歷obj,并且判斷是obj的屬性才拷貝 for(let key in obj){ if(obj.hasOwnProperty(key)){ //如果obj的子屬性是對(duì)象,則進(jìn)行遞歸操作,否則直接賦值 newObj[key] = typeof obj[key] === "object"? deepCopy(obj[key]) :obj[key]; } } return newObj; } ```
!函數(shù)不可拷貝
```JavaScript let arr = { a: 'one', b: ()=>{ console.log('test') } }; let newArr = JSON.parse( JSON.stringify(arr) ); console.log(arr); // {a: "one", b: ()=>{console.log('test')}} console.log(newArr); // {a: "one"} // 函數(shù)沒(méi)有復(fù)制成功 ```
[https://www.notion.so/003-86d95731f5394ff3909864547dac1c21](參考!)