<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          實(shí)現(xiàn)深拷貝的多種方式

          共 4050字,需瀏覽 9分鐘

           ·

          2020-09-17 23:14

          來(lái)源 |?http://www.fly63.com/article/detial/9650

          簡(jiǎn)單來(lái)說(shuō),深拷貝主要是將另一個(gè)對(duì)象的屬性值拷貝過(guò)來(lái)之后,另一個(gè)對(duì)象的屬性值并不受到影響,因?yàn)榇藭r(shí)它自己在堆中開(kāi)辟了自己的內(nèi)存區(qū)域,不受外界干擾。
          淺拷貝主要拷貝的是對(duì)象的引用值,當(dāng)改變對(duì)象的值,另一個(gè)對(duì)象的值也會(huì)發(fā)生變化。?

          1.簡(jiǎn)單深拷貝(一層淺拷貝)

          ①for循環(huán)拷貝

          // 只復(fù)制第一層的淺拷貝function simpleCopy(obj1) {   var obj2 = Array.isArray(obj1) ? [] : {};   for (let i in obj1) {   obj2[i] = obj1[i];  }   return obj2;}var obj1 = {   a: 1,   b: 2,   c: {   d: 3  }}var obj2 = simpleCopy(obj1);obj2.a = 3;obj2.c.d = 4;alert(obj1.a); // 1alert(obj2.a); // 3alert(obj1.c.d); // 4alert(obj2.c.d); // 4

          ②Object.assign()實(shí)現(xiàn)一層深拷貝

           var obj1 = {    a: 1,    b: 2,    c: 3}var obj2 = Object.assign({}, obj1);obj2.b = 5;console.log(obj1.b); // 2console.log(obj2.b); // 5 var obj1 = {    a: 1,    b: 2,    c: ['a','b','c']}var obj2 = Object.assign({}, obj1);obj2.c[1] = 5;console.log(obj1.c); // ["a", 5, "c"]console.log(obj2.c); // ["a", 5, "c"]

          ③slice實(shí)現(xiàn)

          // 對(duì)只有一級(jí)屬性值的數(shù)組對(duì)象使用slicevar a = [1,2,3,4];var b = a.slice();b[0] = 2;alert(a); // 1,2,3,4alert(b); // 2,2,3,4// 對(duì)有多層屬性的數(shù)組對(duì)象使用slicevar a = [1,[1,2],3,4];var b = a.slice();b[1][0] = 2;alert(a); // 1,2,2,3,4alert(b); // 1,2,2,3,4

          ④使用concat()方法

           var a=[1,2,[3,4]] var c=[]; var b=c.concat(a); b[0]=5; b[2][0]=6; console.log(b[0]);//5 console.log(a[0])//1 console.log(b[2][0]);//6 console.log(a[2][0])//6

          ⑤es6的擴(kuò)展運(yùn)算符"..."

           var a=[1,2,[3,4]] var b=[...a]; b[0]=5; b[2][0]=6 console.log(b[0]);//5 console.log(a[0])//1 console.log(b[2][0]);//6 console.log(a[2][0])//6

          ⑥通過(guò)Object.create()實(shí)現(xiàn)

          function deepCopy(obj) {  var copy = Object.create(Object.getPrototypeOf(obj));  var propNames = Object.getOwnPropertyNames(obj);
          propNames.forEach(function(name) { var desc = Object.getOwnPropertyDescriptor(obj, name); Object.defineProperty(copy, name, desc); });
          return copy;}
          var obj1 = { a: 1, b: {bc: 50, dc: 100, be: {bea: 1}} };var obj2 = deepCopy(obj1);obj2.a = 20;obj2.b.bc = 60;console.log(obj1.a)//1console.log(obj2.a)//20console.log(obj1.b.bc)//60console.log(obj2.b.bc)//60

          2.粗暴深拷貝(拋棄對(duì)象的constructor)

          使用jsON.stringify和jsON.parse實(shí)現(xiàn)深拷貝:JSON.stringify把對(duì)象轉(zhuǎn)成字符串,再用JSON.parse把字符串轉(zhuǎn)成新的對(duì)象;

          function deepCopy(obj1){    let _obj = JSON.stringify(obj1);    let obj2 = JSON.parse(_obj);    return obj2;}var a = [1, [1, 2], 3, 4];var b = deepCopy(a);b[1][0] = 2;alert(a); // 1,1,2,3,4alert(b); // 2,2,2,3,4

          缺陷:它會(huì)拋棄對(duì)象的constructor,深拷貝之后,不管這個(gè)對(duì)象原來(lái)的構(gòu)造函數(shù)是什么,在深拷貝之后都會(huì)變成Object;這種方法能正確處理的對(duì)象只有 Number, String, Boolean, Array, 扁平對(duì)象,也就是說(shuō),只有可以轉(zhuǎn)成JSON格式的對(duì)象才可以這樣用,像function沒(méi)辦法轉(zhuǎn)成JSON;

          let obj1 = {   fun:function(){      alert(123);   }}let obj2 = JSON.parse(JSON.stringify(obj1));console.log(typeof obj1.fun); // functionconsole.log(typeof obj2.fun); // undefined

          3.復(fù)雜深拷貝(相對(duì)完美)

          遞歸拷貝實(shí)現(xiàn)深拷貝,解決循環(huán)引用問(wèn)題

          /** * 判斷是否是基本數(shù)據(jù)類型 * @param value */function isPrimitive(value){  return (typeof value === 'string' ||  typeof value === 'number' ||  typeof value === 'symbol' ||  typeof value === 'boolean')}
          /** * 判斷是否是一個(gè)js對(duì)象 * @param value */function isObject(value){ return Object.prototype.toString.call(value) === "[object Object]"}
          /** * 深拷貝一個(gè)值 * @param value */function cloneDeep(value){
          // 記錄被拷貝的值,避免循環(huán)引用的出現(xiàn) let memo = {};
          function baseClone(value){ let res; // 如果是基本數(shù)據(jù)類型,則直接返回 if(isPrimitive(value)){ return value; // 如果是引用數(shù)據(jù)類型,我們淺拷貝一個(gè)新值來(lái)代替原來(lái)的值 }else if(Array.isArray(value)){ res = [...value]; }else if(isObject(value)){ res = {...value}; }
          // 檢測(cè)我們淺拷貝的這個(gè)對(duì)象的屬性值有沒(méi)有是引用數(shù)據(jù)類型。如果是,則遞歸拷貝 Reflect.ownKeys(res).forEach(key=>{ if(typeof res[key] === "object" && res[key]!== null){ //此處我們用memo來(lái)記錄已經(jīng)被拷貝過(guò)的引用地址。以此來(lái)解決循環(huán)引用的問(wèn)題 if(memo[res[key]]){ res[key] = memo[res[key]]; }else{ memo[res[key]] = res[key]; res[key] = baseClone(res[key]) } } }) return res; }
          return baseClone(value)}

          4.ES插件lodash

          import lodash from 'lodash'
          var objects = [1,{ 'a': 1 }, { 'b': 2 }];var deep = lodash.cloneDeep(objects);deep[0] = 2;deep[1].a = 2;console.log(objects[0]);//1console.log(deep[0]);//2console.log(objects[1].a);//1console.log(objects[1].a);//2

          瀏覽 46
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  九九色影院 | 蜜桃传媒一区二区亚洲 | 91人妻人人澡人人爽精品 | 女人大香交毛片 | 欧美精选网页 |