您好,登錄后才能下訂單哦!
這篇文章主要講解了“怎么解決JavaScript的深淺拷貝”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么解決JavaScript的深淺拷貝”吧!
從一則故事講起,昨天因為醫院開不出藥,我拿上藥取小區藥店去買藥,進門之后我問老板有沒有這個藥,老板轉身進去一個小屋子拿了一盒藥,果不其然確實有,藥的名字和毫克一摸一樣,但是盒子的樣子和廠商不一樣,我問老板:“這兩個藥是一種藥嗎,盒子不一樣啊,藥的成分是一樣的嗎?”老板說當然一樣啊,這個就和你去買豬肉一樣,同樣是豬身上的肉,只不過是你去這個超市和去其他超市買場地一樣而已。最后為了安全起見,我還是沒有買那個藥。
"拷貝"分為淺拷貝和深拷貝。它是針對對象
來說的,如果不是對象一切免談。這里的對象可以理解為我拿的那盒藥,淺拷貝
可以理解為老板拿出來的那盒藥,雖然藥的名字和毫克一樣,然后里面的我們不知道是否真的一樣,可能一樣可能不一樣。深拷貝
可以理解為我買到了一摸一樣的藥,一層一層的藥名,毫克,廠商,成分都一樣。
總結:
淺拷貝就是針對對象的屬性依次進行復制,只復制一層,不會遞歸到個屬性復制,會產生引用
問題即內存地址是指的同一地址。簡單來說就是拷貝之后和原對象有關
。
深拷貝就是針對對象的各屬性遞歸復制到新的對象上,內存地址不會指向同一地址。簡單來說就是拷貝之后和元對象無關
。
下面看一個淺拷貝的例子:
let school={'name':"W3Cschool"}; let my = {age:{count:18},name:"W3Cschool億速云"}; let all = {...school,...my}; my.age.count=100; console.log(all); console.log(my);
結果:
{ age: { count: 100 }, name: 'W3Cschool億速云' } { age: { count: 100 }, name: 'W3Cschool億速云' }
結論是:淺拷貝修改拷貝之后的對象上的屬性會把原對象身上的屬性同時修改掉。
下面再看一個深拷貝的例子:
const _ = require("loadsh") let my = {age:{count:18},name:"W3Cschool億速云"}; let all = _.cloneDeep(my); all.age.count =100; console.log(my); console.log(all);
結果:
{ age: { count: 18 }, name: 'W3Cschool億速云' } { age: { count: 100 }, name: 'W3Cschool億速云' }
結論是:深拷貝修改拷貝之后的對象上的屬性不會把原對象身上的屬性同時修改掉。
1.數組方法:slice和concat
slice
let arr = [1,2,3,4]; let arr2 = arr.slice(0) arr2[2]=5; console.log(arr); //[ 1, 2, 3, 4 ] console.log(arr2); //[ 1, 2, 5, 4 ]
當數組里是不是對象的時候從結果上看是深拷貝,在看下面例子
let arr = [{1:1,2:2}]; let arr2 = arr.slice(0) arr2[2]=5; console.log(arr); //[ { '1': 1 }, { '2': 5 } ] console.log(arr2); //[ { '1': 1 }, { '2': 5 } ]
當數組里是對象的時候就變成了淺拷貝
concat
let arr = [1,2,3,4]; let arr2 = [].concat(arr); arr2[2]=5; console.log(arr); //[ 1, 2, 3, 4 ] ? console.log(arr2); //[ 1, 2, 5, 4 ]
當數組里不是對象的時候從結果上看是深拷貝,在看下面例子
let arr = [{1:1},{2:2}]; let arr2 = arr.cancat(0) arr2[1][2]=5; console.log(arr); //[ { '1': 1 }, { '2': 5 } ] ?變成了引用 console.log(arr2); //[ { '1': 1 }, { '2': 5 } ]
當數組里是對象的時候就變成了淺拷貝
總結:只有當數組是一維數組而且不包含對象的時候才是深拷貝
(推薦教程:JavaScript教程)
2.Object.assgin()
let a= {a:1,b:2}; let b= Object.assign({},a); a.a=3; console.log(a) //{a: 3, b: 2} console.log(b) //{a: 1, b: 2} ? let a= {a:1,b:{c:2}}; let b= Object.assign({},a); a.b.c=3; console.log(a) //{a: 1, b: {c:3}} console.log(b) //{a: 1, b: {c:3}} ?變成了引用
總結:Object.assgin如果涉及到嵌套多個對象的話就變成了引用 解決方法:使用JSON.stringify()
先轉化成字符串,再通過JSON.parse()
轉化成對象
3.JSON.parse(JSON.stringify())
let a= {a:1,b:{c:2}}; let b= JSON.parse(JSON.stringify(a)) a.b.c=3; console.log(a) //{a: 1, b: {c:3}} console.log(b) //{a: 1, b: {c:2}} ? let school={'name':"W3Cschool億速云",fn:function(){}}; let my = {age:{count:18},name:"W3Cschool億速云"}; let all=JSON.parse(JSON.stringify({...school,...my})) console.log(all); //{'name':"W3Cschool億速云",age:{count:18}}; //?把fn給丟了
總結: JSON.parse(JSON.stringify()) 這個方法有一定的局限性,會丟失 fn 。
4.手寫深拷貝
let deepClone=(obj)=>{ if(obj==undefined) return obj; //undefined == null if(obj instanceof RegExp) return new RegExp(obj); if(obj instanceof Date) return new Date(obj); if(typeof obj!=="object") return obj; let newObj = new obj.constructor; for(let key in obj){ if(obj.hasOwnProperty(key)){ newObj[key] = deepClone(obj[key]) } } return newObj; } let obj1 = {name:{age:"10"}} let n = deepClone(obj1) obj1.name.age = "231" console.log(n); //{name:{age:"10"}} ? let obj = { name:"W3Cschool億速云" } obj.aaa=obj let n = deepClone(obj1) console.log(n); //死循環了 ?
解決這個問題可以使用WeakMap
let deepClone=(obj,hash=new WeakMap())=>{ if(obj==undefined) return obj; //undefined == null if(obj instanceof RegExp) return new RegExp(obj); if(obj instanceof Date) return new Date(obj); if(typeof obj!=="object") return obj; if(hash.has(obj)) return hash.get(obj); let newObj = new obj.constructor; hash.set(obj,newObj); for(let key in obj){ if(obj.hasOwnProperty(key)){ newObj[key] = deepClone(obj[key],hash) } } return newObj; }
5.lodash的cloneDeep
<br> 源碼地址:https://github.com/lodash/lodash/blob/86a852fe763935bb64c12589df5391fd7d3bb14d/.internal/baseClone.js <br> ```
6.vue-router源碼中的克隆方法
function clone (value) { if (Array.isArray(value)) { return value.map(clone) } else if (value && typeof value === 'object') { const res = {} for (const key in value) { res[key] = clone(value[key]) } return res } else { return value } } let arr = [{1:1},{2:2},function(){}]; let arr2 = clone(arr) arr2[1][2]=5; console.log(arr) //[ { '1': 1 }, { '2': 2 }, [Function (anonymous)] ] ? 深拷貝 console.log(arr2); //[ { '1': 1 }, { '2': 5 }, [Function (anonymous)] ] function extend (a, b) { for (const key in b) { a[key] = b[key] } return a } let b={a:1,b:{c:2}}; let a= extend({},b); a.b.c=5; console.log(a); //{ a: 1, b: { c: 5 } } console.log(b); //{ a: 1, b: { c: 5 } } 淺拷貝
感謝各位的閱讀,以上就是“怎么解決JavaScript的深淺拷貝”的內容了,經過本文的學習后,相信大家對怎么解決JavaScript的深淺拷貝這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。