PageSourceSearch

https://ansonznl.github.io/assets/js/v-5c1251c6.7f294628.js

js ansonznl.github.io collected 2026-10-03 08:39:20 UTC 32,751 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3724],{6053:(n,s,a)=>{a.r(s),a.d(s,{data:()=>p});const p={key:"v-5c1251c6",path:"/articles/JavaScript/JS%E6%B5%85%E6%8B%B7%E8%B4%9D%E4%B8%8E%E6%B7%B1%E6%8B%B7%E8%B4%9D.html",title:"JS 浅拷贝与深拷贝",lang:"en-US",frontmatter:{},excerpt:"",headers:[{level:2,title:"数据类型",slug:"数据类型",children:[]},{level:2,title:"存储方式",slug:"存储方式",children:[]},{level:2,title:"为什么要进行拷贝?",slug:"为什么要进行拷贝",children:[]},{level:2,title:"浅拷贝",slug:"浅拷贝",children:[{level:3,title:"Object.assign()",slug:"object-assign",children:[]},{level:3,title:"扩展运算符",slug:"扩展运算符",children:[]}]},{level:2,title:"深拷贝",slug:"深拷贝",children:[{level:3,title:"JSON.stringify()",slug:"json-stringify",children:[]},{level:3,title:"解决循环引用的问题",slug:"解决循环引用的问题",children:[]},{level:3,title:"自己实现深拷贝",slug:"自己实现深拷贝",children:[]}]},{level:2,title:"使用循环",slug:"使用循环",children:[]},{level:2,title:"参考",slug:"参考",children:[]}],filePathRelative:"articles/JavaScript/JS浅拷贝与深拷贝.md",git:{}}},1278:(n,s,a)=>{a.r(s),a.d(s,{default:()=>x});var p=a(6252);const t=(0,p.uE)('<h1 id="js-浅拷贝与深拷贝" tabindex="-1"><a class="header-anchor" href="#js-浅拷贝与深拷贝" aria-hidden="true">#</a> JS 浅拷贝与深拷贝</h1><h2 id="数据类型" tabindex="-1"><a class="header-anchor" href="#数据类型" aria-hidden="true">#</a> 数据类型</h2><ul><li>基本类型:undefined、null、Boolean、String、Number、Symbol</li><li>引用类型:Object、Array、Date、Function、RegExp 等</li></ul><h2 id="存储方式" tabindex="-1"><a class="header-anchor" href="#存储方式" aria-hidden="true">#</a> 存储方式</h2><ul><li>基本类型:基本类型值在内存中占据固定大小,保存在<code>栈内存</code>当中,(不包含<code>闭包</code>中的变量)</li><li>引用类型:引用类型保存在<code>堆内存</code>中,而栈内存存储的是堆内存中的存储<code>地址</code>(引用)。</li></ul><h2 id="为什么要进行拷贝" tabindex="-1"><a class="header-anchor" href="#为什么要进行拷贝" aria-hidden="true">#</a> 为什么要进行拷贝?</h2><p>看个例子:</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">let</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span>\n  value<span class="token operator">:</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">,</span>\n<span class="token punctuation">}</span><span class="token punctuation">;</span>\n<span class="token keyword">let</span> obj2 <span class="token operator">=</span> obj1<span class="token punctuation">;</span>\nobj2<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token string">&quot;b&quot;</span><span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//{ value: &#39;b&#39; }</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1 <span class="token operator">===</span> obj2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>本来只想改变<code>obj2</code>的 <code>value</code> 的值,但是改变之后连<code>obj1</code>的值也一同改变了,很显然,这不是我们想要的的结果。</p><p>因为对象是引用类型,所以赋值时的操作仅是赋予相同的地址,当对其中一个对象进行操作时,就会影响其他的对象。解决这个问题就需要使用拷贝了。</p><p>拷贝的方式分两种:</p><ul><li>浅拷贝 <ul><li>基本类型:拷贝值</li><li>引用类型:拷贝对象引用。</li></ul></li><li>深拷贝 <ul><li>基本类型:拷贝值</li><li>引用类型:会创建一个新的引用,将之前的对象完整的拷贝一份出来,并添加至新的引用当中。</li></ul></li></ul><h2 id="浅拷贝" tabindex="-1"><a class="header-anchor" href="#浅拷贝" aria-hidden="true">
1#</a> 浅拷贝</h2><h3 id="object-assign" tabindex="-1"><a class="header-anchor" href="#object-assign" aria-hidden="true">#</a> Object.assign()</h3><p>使用原生的 <code>Object.assign()</code> 方法就可以实现引用类型的浅拷贝</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">let</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span>\n  value<span class="token operator">:</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">,</span>\n<span class="token punctuation">}</span><span class="token punctuation">;</span>\n<span class="token keyword">let</span> obj2 <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">assign</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> obj1<span class="token punctuation">)</span><span class="token punctuation">;</span>\nobj2<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token string">&quot;b&quot;</span><span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//{ value: &#39;a&#39; }</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>但是如果拷贝的源对象当中包含对象时,<code>OBject.assign()</code>方法只会拷贝对象的引用地址</p><h3 id="扩展运算符" tabindex="-1"><a class="header-anchor" href="#扩展运算符" aria-hidden="true">#</a> 扩展运算符</h3><p>使用 ES6 的扩展运算符也可以达到浅拷贝的效果</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">let</span> arr1 <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>\n<span class="token keyword">let</span> arr2 <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>arr1<span class="token punctuation">]</span><span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arr1 <span class="token operator">===</span> arr2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//false</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>输出 <code>false</code> 就说明克隆成功了,对象可以这么搞</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">let</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span>\n  value<span class="token operator">:</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">,</span>\n  arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span>\n<span class="token punctuation">}</span><span class="token punctuation">;</span>\n<span class="token keyword">let</span> obj2 <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span>obj1 <span class="token punctuation">}</span><span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1 <span class="token operator">===</span> obj2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">
1// false</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1<span class="token punctuation">.</span>arr <span class="token operator">===</span> obj2<span class="token punctuation">.</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>输出 <code>false</code> 就说明克隆成功了,但是里面的数组却克隆失败了,是因为扩展运算符在复制引用类型时,复制的是地址。</p><p>这种比较试适合简单的单个数组或者对象使用,简单又方便</p><h2 id="深拷贝" tabindex="-1"><a class="header-anchor" href="#深拷贝" aria-hidden="true">#</a> 深拷贝</h2><h3 id="json-stringify" tabindex="-1"><a class="header-anchor" href="#json-stringify" aria-hidden="true">#</a> JSON.stringify()</h3><p>如果要拷贝的对象中包含对象,就需要深拷贝了,一般使用原生的方法<code>JSON.parse(JSON.stringify(obj))</code></p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">let</span> obj1 <span class="token operator">=</span> <span class="token punctuation">{</span>\n  value<span class="token operator">:</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">,</span>\n  obj<span class="token operator">:</span> <span class="token punctuation">{</span>\n    value<span class="token operator">:</span> <span class="token string">&quot;b&quot;</span><span class="token punctuation">,</span>\n  <span class="token punctuation">}</span><span class="token punctuation">,</span>\n  arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">,</span>\n<span class="token punctuation">}</span><span class="token punctuation">;</span>\n<span class="token keyword">let</span> obj2 <span class="token operator">=</span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>obj1<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1<span class="token punctuation">.</span>arr <span class="token operator">===</span> obj2<span class="token punctuation">.</span>arr<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj1<span class="token punctuation">.</span>obj <span class="token operator">===</span> obj2<span class="token punctuation">.</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>输出 <code>false</code> 就说明克隆成功了</p><p>这个也会有一些缺陷,比如 <code>undefined</code> 或者有函数的时候就会出现问题,最好的方法是使用递归函数。</p>',30),e=(0,p.Uk)("这个可以参考"),o={href:"https://github.com/lodash/lodash/blob/master/cloneDeep.js",target:"_blank",rel:"noopener noreferrer"},c=(0,p.Uk)("loadsh cloneDeep"),l=(0,p._)("h3",{id:"解决循环引用的问题",tabindex:"-1"},[(0,p._)("a",{class:"header-anchor",href:"#解决循环引用的问题","aria-hidden":"true"},"#"),(0,p.Uk)(" 解决循环引用的问题")],-1),u=(0,p._)("p",null,"有种特殊情况需注意就是对象存在循环引用的情况,即对象的属性直接的引用了自身的情况,解决循环引用问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系,当需要拷贝当前对象时,先去存储空间中找,有没有拷贝过这个对象,如果有的话直接返回,如果没有的话继续拷贝,这样就巧妙化解的循环引用的问题。",-1),r=(0,p.Uk)("关于这块如有疑惑,请仔细阅读"),i={href:"https://segmentfault.com/a/1190000020255831",target:"_blank",rel:"noopener noreferrer"},k=(0,p.Uk)("ConardLi 大佬如何写出一个惊艳面试官的深拷贝?"),b=(0,p.Uk)("这篇文章。"),d=(0,p.uE)('<h3 id="自己实现深拷贝" tabindex="-1"><a class="header-anchor" href="#自己实现深拷贝" aria-hidden="true">
1#</a> 自己实现深拷贝</h3><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">function</span> <span class="token function">deepClone</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> hash <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">WeakMap</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n  <span class="token keyword">if</span> <span class="token punctuation">(</span>obj <span class="token operator">===</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">return</span> obj<span class="token punctuation">;</span> <span class="token comment">// 如果是null或者undefined我就不进行拷贝操作</span>\n  <span class="token keyword">if</span> <span class="token punctuation">(</span>obj <span class="token keyword">instanceof</span> <span class="token class-name">Date</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>\n  <span class="token keyword">if</span> <span class="token punctuation">(</span>obj <span class="token keyword">instanceof</span> <span class="token class-name">RegExp</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">RegExp</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>\n  <span class="token comment">// 可能是对象或者普通的值  如果是函数的话是不需要深拷贝</span>\n  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> obj <span class="token operator">!==</span> <span class="token string">&quot;object&quot;</span><span class="token punctuation">)</span> <span class="token keyword">return</span> obj<span class="token punctuation">;</span>\n  <span class="token comment">// 是对象的话就要进行深拷贝</span>\n  <span class="token keyword">if</span> <span class="token punctuation">(</span>hash<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> hash<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>\n  <span class="token keyword">let</span> cloneObj <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">obj<span class="token punctuation">.</span>constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n  <span class="token comment">// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身</span>\n  hash<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> cloneObj<span class="token punctuation">)</span><span class="token punctuation">;</span>\n  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> key <span class="token keyword">in</span> obj<span class="token punctuation">)</span> <span class="token punctuation">{</span>\n    <span class="token keyword">if</span> <span class="token punctuation">(</span>obj<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
1\n      <span class="token comment">// 实现一个递归拷贝</span>\n      cloneObj<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">deepClone</span><span class="token punctuation">(</span>obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">,</span> hash<span class="token punctuation">)</span><span class="token punctuation">;</span>\n    <span class="token punctuation">}</span>\n  <span class="token punctuation">}</span>\n  <span class="token keyword">return</span> cloneObj<span class="token punctuation">;</span>\n<span class="token punctuation">}</span>\n<span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> address<span class="token operator">:</span> <span class="token punctuation">{</span> x<span class="token operator">:</span> <span class="token number">100</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>\nobj<span class="token punctuation">.</span>o <span class="token operator">=</span> obj<span class="token punctuation">;</span> <span class="token comment">// 对象存在循环引用的情况</span>\n<span class="token keyword">let</span> d <span class="token operator">=</span> <span class="token function">deepClone</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span>\nobj<span class="token punctuation">.</span>address<span class="token punctuation">.</span>x <span class="token operator">=</span> <span class="token number">200</span><span class="token punctuation">;</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>d <span class="token operator">===</span> obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false 克隆成功</span>\nconsole<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>d<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// { name: 1, address: { x: 100 }, o: [Circular] }</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><h2 id="使用循环" tabindex="-1"><a class="header-anchor" href="#使用循环" aria-hidden="true">#</a> 使用循环</h2><p>递归容易爆栈。</p><p>其实破解递归爆栈的方法有两条路,第一种是消除尾递归,但在这个例子中貌似行不通,第二种方法就是干脆不用递归,改用循环,</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code><span class="token keyword">function</span> <span class="token function">cloneLoop</span><span class="token punctuation">(</span><span class="token parameter">x</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n    <span class="token keyword">const</span> root <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>\n\n    <span class="token comment">// 栈</span>\n    <span class="token keyword">const</span> loopList <span class="token operator">=</span> <span class="token punctuation">[</span>
1\n        <span class="token punctuation">{</span>\n            parent<span class="token operator">:</span> root<span class="token punctuation">,</span>\n            key<span class="token operator">:</span> <span class="token keyword">undefined</span><span class="token punctuation">,</span>\n            data<span class="token operator">:</span> x<span class="token punctuation">,</span>\n        <span class="token punctuation">}</span>\n    <span class="token punctuation">]</span><span class="token punctuation">;</span>\n\n    <span class="token keyword">while</span><span class="token punctuation">(</span>loopList<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>\n        <span class="token comment">// 深度优先</span>\n        <span class="token keyword">const</span> node <span class="token operator">=</span> loopList<span class="token punctuation">.</span><span class="token function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n        <span class="token keyword">const</span> <span class="token punctuation">{</span>parent<span class="token punctuation">,</span> key<span class="token punctuation">,</span> data<span class="token punctuation">}</span> <span class="token operator">=</span> node<span class="token punctuation">;</span>\n        <span class="token comment">// 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素</span>\n        <span class="token keyword">let</span> res <span class="token operator">=</span> parent<span class="token punctuation">;</span>\n        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> key <span class="token operator">!==</span> <span class="token string">&#39;undefined&#39;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n            parent<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>\n            res <span class="token operator">=</span> parent<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span>\n        <span class="token punctuation">}</span>\n\n        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> k <span class="token keyword">in</span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span>\n            <span class="token keyword">if</span> <span class="token punctuation">(</span>data<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span>k<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n                <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> data<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">&#39;object&#39;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>\n                    <span class="token comment">// 下一次循环</span>\n                    loopList<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span>\n                        parent<span class="token operator">:</span> res<span class="token punctuation">,</span>\n                        key<span class="token operator">:</span> k<span class="token punctuation">,</span>\n                        data<span class="token operator">:</span> data<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">,</span>
1\n                    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n                <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>\n                    res<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> data<span class="token punctuation">[</span>k<span class="token punctuation">]</span><span class="token punctuation">;</span>\n                <span class="token punctuation">}</span>\n            <span class="token punctuation">}</span>\n        <span class="token punctuation">}</span>\n    <span class="token punctuation">}</span>\n\n    <span class="token keyword">return</span> root<span class="token punctuation">;</span>\n<span class="token punctuation">}</span>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br></div></div><p>用循环遍历一棵树,需要借助一个栈,当栈为空时就遍历完了,栈里面存储下一个需要拷贝的节点</p><p>首先我们往栈里放入种子数据,key用来存储放哪一个父元素的那一个子元素拷贝对象</p><p>然后遍历当前节点下的子元素,如果是对象就放到栈里,否则直接拷贝</p><div class="language-javascript ext-js line-numbers-mode"><pre class="language-javascript"><code>\n</code></pre><div class="line-numbers"><span class="line-number">1</span><br></div></div><p>改用循环后,再也不会出现爆栈的问题了,但是对于循环引用依然无力应对</p><h2 id="参考" tabindex="-1"><a class="header-anchor" href="#参考" aria-hidden="true">#</a> 参考</h2>',12),m={href:"https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign",target:"_blank",rel:"noopener noreferrer"},h=(0,p.Uk)("MDN-Object.assign"),j={href:"https://es6.ruanyifeng.com/#docs/array#%E6%89%A9%E5%B1%95%E8%BF%90%E7%AE%97%E7%AC%A6",target:"_blank",rel:"noopener noreferrer"},g=(0,p.Uk)("ES6-扩展运算符"),f={href:"https://juejin.im/post/6844904197595332622#heading-13",target:"_blank",rel:"noopener noreferrer"},y=(0,p.Uk)("juejin-浅拷贝与深拷贝"),v={href:"https://segmentfault.com/a/1190000020255831",target:"_blank",rel:"noopener noreferrer"},w=(0,p.Uk)("如何写出一个惊艳面试官的深拷贝?"),x={render:function(n,s){const a=(0,p.up)("OutboundLink");return(0,p.wg)(),(0,p.iD)(p.HY,null,[t,(0,p._)("p",null,[e,(0,p._)("a",o,[c,(0,p.Wm)(a)])]),l,u,(0,p._)("p",null,[r,(0,p._)("a",i,[k,(0,p.Wm)(a)]),b]),d,(0,p._)("ul",null,[(0,p._)("li",null,[(0,p._)("a",m,[h,(0,p.Wm)(a)])]),(0,p._)("li",null,[(0,p._)("a",j,[g,(0,p.Wm)(a)])]),(0,p._)("li",null,[(0,p._)("a",f,[y,(0,p.Wm)(a)])]),(0,p._)("li",null,[(0,p._)("a",v,[w,(0,p.Wm)(a)])])])],64)}}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.