<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # 概念 其實深拷貝和淺拷貝都是針對的引用類型,JS中的變量類型分為值類型(基本類型)和引用類型;對值類型進行復制操作會對值進行一份拷貝,而對引用類型賦值,則會進行地址的拷貝,最終兩個變量指向同一份數據 ~~~ // 基本類型 var a = 1; var b = a; a = 2; console.log(a, b); // 2, 1 ,a b指向不同的數據 // 引用類型指向同一份數據 var a = {c: 1}; var b = a; a.c = 2; console.log(a.c, b.c); // 2, 2 全是2,a b指向同一份數據 ~~~ 對于引用類型,會導致a b指向同一份數據,此時如果對其中一個進行修改,就會影響到另外一個,有時候這可能不是我們想要的結果,如果對這種現象不清楚的話,還可能造成不必要的bug 那么如何切斷a和b之間的關系呢,可以拷貝一份a的數據,根據拷貝的層級不同可以分為淺拷貝和深拷貝,淺拷貝就是只進行一層拷貝,深拷貝就是無限層級拷貝 ~~~ var a1 = {b: {c: {}}; var a2 = shallowClone(a1); // 淺拷貝 a2.b.c === a1.b.c // true var a3 = clone(a1); // 深拷貝 a3.b.c === a1.b.c // false ~~~ <br> # 深克隆需要注意的問題 * 入參類型檢查 * 當數據量較大并層次很深時,使用遞歸函數會導致棧溢出,而此處又無法使用尾遞歸,該怎么處理 * typeof Date,Math,RegExp,Function,Null 都返回Object 該怎么處理 * Date,RegExp,Function 應該如何克隆 * 當對象的兩個屬性v,s引用同一個對象時,克隆之后也應該引用同一個對象 * 對象的原型prototype 如何克隆 * 屬性的getOwnPropertyDescriptor如何克隆 * for-in遍歷的是原型鏈,需要用hasOwnProperty 判斷是否是自有屬性 * … # 淺拷貝 ## 方法一 ~~~ function shallowClone(source) { var target = {}; for(var i in source) { if (source.hasOwnProperty(i)) { target[i] = source[i]; } } return target; } ~~~ ## 方法二 ~~~ Object.assign(target, ...sources) ~~~ ## 方法三 ~~~ let a = { age: 1 } let b = { ...a } a.age = 2 console.log(b.age) // 1 ~~~ <br> # 深拷貝 ## 方法一 ~~~ function clone(source) { var target = {}; for(var i in source) { if (source.hasOwnProperty(i)) { if (typeof source[i] === 'object') { target[i] = clone(source[i]); // 注意這里 } else { target[i] = source[i]; } } } return target; } ~~~ 問題 * 沒有對參數做檢驗 * 判斷是否對象的邏輯不夠嚴謹 * 沒有考慮數組的兼容 * **沒有處理棧溢出** * 沒有處理**循環引用** ## 方法二 ~~~ function cloneJSON(source) { return JSON.parse(JSON.stringify(source)); } ~~~ 問題 * **沒有處理棧溢出** * 非JSON格式的值(undefined、函數等)會被忽略 ## 方法三 ~~~ // 定義函數獲取數據類型 function _getDataType(data) { return Object.prototype.toString.call(data).slice(8, -1); } ~~~ ~~~ // 定義函數克隆RegExp類型 function copyRegExp(regExp) { let attrs = ''; if (regExp.global) attrs += 'g'; if (regExp.ignoreCase) attrs += 'i'; if (regExp.multiline) attrs += 'm'; let newRegExp = new RegExp(regExp, attrs); newRegExp.lastIndex = regExp.lastIndex; return newRegExp; } ~~~ ~~~ // 定義深克隆函數 function clone(x) { // String Number Boolean Undefined Null 返回自身 if (x == null || typeof x !== 'object') return x; // RegExp Date Function 克隆 let type = _getDataType(x); let root; switch (type) { case 'RegExp': return copyRegExp(x); case 'Date': return new Date(x.getTime()); case 'Function': return x; case 'Array': root = []; break; default: root = Object.create(Object.getPrototypeOf(x)); } // Array Object 克隆 // 用來去重 解決原數據中多個屬性引用同一對象克隆后不相同問題 const uniqueList = []; // 使用棧結構解決遞歸爆棧問題 const stack = [ { parent: root, key: undefined, data: x, } ]; // 深度優先循環 while (stack.length) { const {parent, key, data} = stack.pop(); // 初始化賦值目標,key為undefined則拷貝到父元素,否則拷貝到子元素 let res = parent; if (typeof key !== 'undefined') { let type = _getDataType(data); switch (type) { case 'RegExp': parent[key] = copyRegExp(data); continue; case 'Date': parent[key] = new Date(data.getTime()); continue; case 'Function': parent[key] = data; continue; case 'Array': res = parent[key] = []; break; default: let proto = Object.getPrototypeOf(data); res = parent[key] = Object.create(proto); } } //數據引用已經存在則賦值并退出本次循環,不存在則緩存 let uniqueData = uniqueList.find(item => item.source === data); if (uniqueData) { parent[key] = uniqueData.target; continue; } else { uniqueList.push({ source: data, target: res, }); } for (let k in data) { if (data.hasOwnProperty(k)) { if (data[k] == null || typeof data[k] !== 'object') { // 基礎類型克隆 let descriptor=Object.getOwnPropertyDescriptor(data,k); Object.defineProperty(res,k,descriptor); } else { // 引用類型加入stack循環處理 stack.push({ parent: res, key: k, data: data[k], }); } } } } return root; } ~~~ # 參考資料 [深拷貝的終極探索(90%的人都不知道)](https://juejin.im/post/5bc1ae9be51d450e8b140b0c) [js 深克隆(考慮到類型檢查,遞歸爆棧,相同引用,Date和Function等特殊類型克隆,原型克隆)](https://blog.csdn.net/lyt_angularjs/article/details/86599820)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看