[{"data":1,"prerenderedAt":1797},["ShallowReactive",2],{"article-js-deep-copy":3},{"id":4,"title":5,"body":6,"category":1783,"createdAt":1785,"description":1786,"extension":1787,"index":1788,"meta":1789,"navigation":245,"path":1790,"publish":245,"seo":1791,"series":1788,"seriesTitle":1788,"stem":1792,"tag":1793,"thumbnail":1788,"updatedAt":1788,"__hash__":1796},"articles\u002Farticles\u002Fjs-deep-copy.md","jsで配列内のオブジェクトの値が連動してしまう原因と対処法",{"type":7,"value":8,"toc":1771},"minimark",[9,18,189,203,207,215,338,345,350,353,358,361,366,373,386,388,396,399,599,622,680,683,685,688,691,700,704,715,884,887,891,903,1086,1093,1302,1305,1309,1319,1326,1516,1519,1523,1526,1581,1584,1764,1767],[10,11,12,13,17],"p",{},"こんにちはjunです。vue.jsとかでアプリを作るととき、一覧ページや複数個のデータを出力する時はオブジェクトが内包された配列データを使用することが多いと思います。例としては以下のような「記事一覧」用の",[14,15,16],"code",{},"posts","データです。",[19,20,25],"pre",{"className":21,"code":22,"language":23,"meta":24,"style":24},"language-javascript shiki shiki-themes material-theme-ocean","const posts = [\n    {id:1,title:\"記事タイトル１\",content:\"...\"},\n    {id:2,title:\"記事タイトル２\",content:\"...\"},\n    {id:3,title:\"記事タイトル３\",content:\"...\"},\n    \u002F\u002F ...\n]\n","javascript","",[14,26,27,47,98,137,176,183],{"__ignoreMap":24},[28,29,32,36,40,44],"span",{"class":30,"line":31},"line",1,[28,33,35],{"class":34},"sJ14y","const",[28,37,39],{"class":38},"s0W1g"," posts ",[28,41,43],{"class":42},"sAklC","=",[28,45,46],{"class":38}," [\n",[28,48,50,53,57,60,64,67,70,72,75,79,81,83,86,88,90,93,95],{"class":30,"line":49},2,[28,51,52],{"class":42},"    {",[28,54,56],{"class":55},"s-wAU","id",[28,58,59],{"class":42},":",[28,61,63],{"class":62},"sx098","1",[28,65,66],{"class":42},",",[28,68,69],{"class":55},"title",[28,71,59],{"class":42},[28,73,74],{"class":42},"\"",[28,76,78],{"class":77},"sfyAc","記事タイトル１",[28,80,74],{"class":42},[28,82,66],{"class":42},[28,84,85],{"class":55},"content",[28,87,59],{"class":42},[28,89,74],{"class":42},[28,91,92],{"class":77},"...",[28,94,74],{"class":42},[28,96,97],{"class":42},"},\n",[28,99,101,103,105,107,110,112,114,116,118,121,123,125,127,129,131,133,135],{"class":30,"line":100},3,[28,102,52],{"class":42},[28,104,56],{"class":55},[28,106,59],{"class":42},[28,108,109],{"class":62},"2",[28,111,66],{"class":42},[28,113,69],{"class":55},[28,115,59],{"class":42},[28,117,74],{"class":42},[28,119,120],{"class":77},"記事タイトル２",[28,122,74],{"class":42},[28,124,66],{"class":42},[28,126,85],{"class":55},[28,128,59],{"class":42},[28,130,74],{"class":42},[28,132,92],{"class":77},[28,134,74],{"class":42},[28,136,97],{"class":42},[28,138,140,142,144,146,149,151,153,155,157,160,162,164,166,168,170,172,174],{"class":30,"line":139},4,[28,141,52],{"class":42},[28,143,56],{"class":55},[28,145,59],{"class":42},[28,147,148],{"class":62},"3",[28,150,66],{"class":42},[28,152,69],{"class":55},[28,154,59],{"class":42},[28,156,74],{"class":42},[28,158,159],{"class":77},"記事タイトル３",[28,161,74],{"class":42},[28,163,66],{"class":42},[28,165,85],{"class":55},[28,167,59],{"class":42},[28,169,74],{"class":42},[28,171,92],{"class":77},[28,173,74],{"class":42},[28,175,97],{"class":42},[28,177,179],{"class":30,"line":178},5,[28,180,182],{"class":181},"sC9rS","    \u002F\u002F ...\n",[28,184,186],{"class":30,"line":185},6,[28,187,188],{"class":38},"]\n",[10,190,191,192,197,198,202],{},"今回の記事で解説する内容は上記のような配列を別の変数に格納した時、スプレッド構文を使用して配列を生成したにもかかわらず、オブジェクト内の値が連動してしまったときの対処と原因について解説します。「どんなデータの状況だったか」という実装背景から話すので、ささっと原因からは知りたい人は「",[193,194,196],"a",{"href":195},"#%E5%8E%9F%E5%9B%A0","原因","」へ、解決方法だけ知りたい人は「",[193,199,201],{"href":200},"#%E5%AF%BE%E5%87%A6%E6%B3%95","対処法","」へ移動してください。",[204,205,206],"h2",{"id":206},"実装背景",[10,208,209,210,214],{},"vue.jsで編集画面を実装していた時です。編集画面は「入力された新しい値」と「登録済みの値（DBにある値）」を持たせておき、一部でその差分を確認できるようにするという",[211,212,213],"del",{},"面倒な","実装がありました。内容としては「1日の予定表」みたいなもので、以下のようなデータ構造です。",[19,216,218],{"className":21,"code":217,"language":23,"meta":24,"style":24},"const DATA_FROM_DB = response.data;\n\nconsole.log(DATA_FROM_DB);\n\u002F**\n{\n    date:\"2021-11-01\", \n    memo:\"...\",\n    todo:   \u002F\u002F この日の予定を入れる。\n    [\n        {id:1,content:\"AAAA\"},\n        {id:2,content:\"BBBB\"},\n        {id:3,content:\"CCCC\"},\n        ...\n    ]\n}\n**\u002F\n\n",[14,219,220,241,247,263,268,273,278,284,290,296,302,308,314,320,326,332],{"__ignoreMap":24},[28,221,222,224,227,229,232,235,238],{"class":30,"line":31},[28,223,35],{"class":34},[28,225,226],{"class":38}," DATA_FROM_DB ",[28,228,43],{"class":42},[28,230,231],{"class":38}," response",[28,233,234],{"class":42},".",[28,236,237],{"class":38},"data",[28,239,240],{"class":42},";\n",[28,242,243],{"class":30,"line":49},[28,244,246],{"emptyLinePlaceholder":245},true,"\n",[28,248,249,252,254,258,261],{"class":30,"line":100},[28,250,251],{"class":38},"console",[28,253,234],{"class":42},[28,255,257],{"class":256},"sdLwU","log",[28,259,260],{"class":38},"(DATA_FROM_DB)",[28,262,240],{"class":42},[28,264,265],{"class":30,"line":139},[28,266,267],{"class":181},"\u002F**\n",[28,269,270],{"class":30,"line":178},[28,271,272],{"class":181},"{\n",[28,274,275],{"class":30,"line":185},[28,276,277],{"class":181},"    date:\"2021-11-01\", \n",[28,279,281],{"class":30,"line":280},7,[28,282,283],{"class":181},"    memo:\"...\",\n",[28,285,287],{"class":30,"line":286},8,[28,288,289],{"class":181},"    todo:   \u002F\u002F この日の予定を入れる。\n",[28,291,293],{"class":30,"line":292},9,[28,294,295],{"class":181},"    [\n",[28,297,299],{"class":30,"line":298},10,[28,300,301],{"class":181},"        {id:1,content:\"AAAA\"},\n",[28,303,305],{"class":30,"line":304},11,[28,306,307],{"class":181},"        {id:2,content:\"BBBB\"},\n",[28,309,311],{"class":30,"line":310},12,[28,312,313],{"class":181},"        {id:3,content:\"CCCC\"},\n",[28,315,317],{"class":30,"line":316},13,[28,318,319],{"class":181},"        ...\n",[28,321,323],{"class":30,"line":322},14,[28,324,325],{"class":181},"    ]\n",[28,327,329],{"class":30,"line":328},15,[28,330,331],{"class":181},"}\n",[28,333,335],{"class":30,"line":334},16,[28,336,337],{"class":181},"**\u002F\n",[10,339,340,341,344],{},"上記データの ",[14,342,343],{},"DATA_FROM_DB.todo"," の変更前のデータを確認できるようにする必要があります。実装のためには別の定数なりに格納しておく必要があります。私はもちろん「参照渡し」・「値渡し」の概念は知っていたので、",[10,346,347],{},[14,348,349],{},"const OLD_TODO_DATA = DATA_FROM_DB.todo;",[10,351,352],{},"なんてことせず、",[10,354,355],{},[14,356,357],{},"const OLD_TODO_DATA = [...DATA_FROM_DB.todo];",[10,359,360],{},"とスプレッド構文を使用して新しく配列を生成しました。これで大丈夫だろと思っていましたが。。",[362,363,365],"h3",{"id":364},"事件は起きた","事件は起きた。",[10,367,368,369,372],{},"新しいTODOと元のTODOを画面上に表示させて、TODO編集をテストしていた時です。新しくTODOを変更しているはずなに、古い ",[14,370,371],{},"OLD_TODO_DATA","から表示している内容も同じ変更した値に切り替わっていました。つまり値が連動していたのです。「WHY?」と声を出してしまいました。開発ツールで見ていても同じ値になっていることが確認できました。値が参照渡しされているとすぐに気づきましたが、「スプレッド構文を使用したのに...」と対処方法ずっと考えていました。",[374,375,379,380,385],"div",{"className":376},[377,378],"alert","alert-info","\nここでは値渡しと参照渡しの概念は解説しません。知らない方は",[193,381,384],{"target":382,"href":383},"_blank","https:\u002F\u002Fwww.google.com\u002Fsearch?q=js+%E5%80%A4%E6%B8%A1%E3%81%97+%E5%8F%82%E7%85%A7%E6%B8%A1%E3%81%97&oq=js+%E5%80%A4%E6%B8%A1%E3%81%97+%E5%8F%82%E7%85%A7%E6%B8%A1%E3%81%97&aqs=chrome..69i57.290j0j7&sourceid=chrome&ie=UTF-8","「js 値渡し 参照渡し」","でググってください。\n",[204,387,196],{"id":196},[10,389,390,391,395],{},"原因は内包されたオブジェクトが参照渡しされていたからなのです。スプレッド構文は使用しましたが、これはあくまで",[392,393,394],"strong",{},"別の配列","を作っただけであり、中身のオブジェクトの参照は維持されて（コピー元を参照して）いたのです。",[10,397,398],{},"以下のような実験をコンソールでしてみます。",[19,400,402],{"className":21,"code":401,"filename":251,"language":23,"meta":24,"style":24},"> const origin =[{id:1,content:\"1111\"},{id:2,content:\"2222\"}];\n\n> const passbyval = origin;\n\n> const spred = [...origin];\n\n> origin === passbyval;\n\u002F\u002F true\n\n> origin === spred;\n\u002F\u002F false\n\n> origin[0] === spred[0];\n\u002F\u002F true\n\u002F\u002F WHY!?\n",[14,403,404,472,476,492,496,517,521,535,540,544,557,562,566,590,594],{"__ignoreMap":24},[28,405,406,409,412,415,417,420,423,425,427,429,431,433,435,437,440,442,445,447,449,451,453,455,457,459,462,464,467,470],{"class":30,"line":31},[28,407,408],{"class":42},">",[28,410,411],{"class":34}," const",[28,413,414],{"class":38}," origin ",[28,416,43],{"class":42},[28,418,419],{"class":38},"[",[28,421,422],{"class":42},"{",[28,424,56],{"class":55},[28,426,59],{"class":42},[28,428,63],{"class":62},[28,430,66],{"class":42},[28,432,85],{"class":55},[28,434,59],{"class":42},[28,436,74],{"class":42},[28,438,439],{"class":77},"1111",[28,441,74],{"class":42},[28,443,444],{"class":42},"},{",[28,446,56],{"class":55},[28,448,59],{"class":42},[28,450,109],{"class":62},[28,452,66],{"class":42},[28,454,85],{"class":55},[28,456,59],{"class":42},[28,458,74],{"class":42},[28,460,461],{"class":77},"2222",[28,463,74],{"class":42},[28,465,466],{"class":42},"}",[28,468,469],{"class":38},"]",[28,471,240],{"class":42},[28,473,474],{"class":30,"line":49},[28,475,246],{"emptyLinePlaceholder":245},[28,477,478,480,482,485,487,490],{"class":30,"line":100},[28,479,408],{"class":42},[28,481,411],{"class":34},[28,483,484],{"class":38}," passbyval ",[28,486,43],{"class":42},[28,488,489],{"class":38}," origin",[28,491,240],{"class":42},[28,493,494],{"class":30,"line":139},[28,495,246],{"emptyLinePlaceholder":245},[28,497,498,500,502,505,507,510,512,515],{"class":30,"line":178},[28,499,408],{"class":42},[28,501,411],{"class":34},[28,503,504],{"class":38}," spred ",[28,506,43],{"class":42},[28,508,509],{"class":38}," [",[28,511,92],{"class":42},[28,513,514],{"class":38},"origin]",[28,516,240],{"class":42},[28,518,519],{"class":30,"line":185},[28,520,246],{"emptyLinePlaceholder":245},[28,522,523,525,527,530,533],{"class":30,"line":280},[28,524,408],{"class":42},[28,526,414],{"class":38},[28,528,529],{"class":42},"===",[28,531,532],{"class":38}," passbyval",[28,534,240],{"class":42},[28,536,537],{"class":30,"line":286},[28,538,539],{"class":181},"\u002F\u002F true\n",[28,541,542],{"class":30,"line":292},[28,543,246],{"emptyLinePlaceholder":245},[28,545,546,548,550,552,555],{"class":30,"line":298},[28,547,408],{"class":42},[28,549,414],{"class":38},[28,551,529],{"class":42},[28,553,554],{"class":38}," spred",[28,556,240],{"class":42},[28,558,559],{"class":30,"line":304},[28,560,561],{"class":181},"\u002F\u002F false\n",[28,563,564],{"class":30,"line":310},[28,565,246],{"emptyLinePlaceholder":245},[28,567,568,570,573,576,579,581,584,586,588],{"class":30,"line":316},[28,569,408],{"class":42},[28,571,572],{"class":38}," origin[",[28,574,575],{"class":62},"0",[28,577,578],{"class":38},"] ",[28,580,529],{"class":42},[28,582,583],{"class":38}," spred[",[28,585,575],{"class":62},[28,587,469],{"class":38},[28,589,240],{"class":42},[28,591,592],{"class":30,"line":322},[28,593,539],{"class":181},[28,595,596],{"class":30,"line":328},[28,597,598],{"class":181},"\u002F\u002F WHY!?\n",[10,600,601,602,605,606,609,610,613,614,617,618,621],{},"上記が示すとおり、スプレッド構文を使用することで配列としては別物の",[14,603,604],{},"origin === copy"," は",[14,607,608],{},"false","となり、値渡しの",[14,611,612],{},"origin === passbyval ","は",[14,615,616],{},"true","となります。ただし同じindexのオブジェクトを比較すると、なんと同じになっています。値を変えてみると",[14,619,620],{},"spred","も変更されているのが分かります。",[19,623,625],{"className":21,"code":624,"filename":251,"language":23,"meta":24,"style":24},"> origin[0].content = \"changed!\";\n\n> spred[0];\n\u002F\u002F {id: 1, content: 'changed!'}\n\u002F\u002F contentが変更されている\n",[14,626,627,654,658,670,675],{"__ignoreMap":24},[28,628,629,631,633,635,637,639,642,644,647,650,652],{"class":30,"line":31},[28,630,408],{"class":42},[28,632,572],{"class":38},[28,634,575],{"class":62},[28,636,469],{"class":38},[28,638,234],{"class":42},[28,640,641],{"class":38},"content ",[28,643,43],{"class":42},[28,645,646],{"class":42}," \"",[28,648,649],{"class":77},"changed!",[28,651,74],{"class":42},[28,653,240],{"class":42},[28,655,656],{"class":30,"line":49},[28,657,246],{"emptyLinePlaceholder":245},[28,659,660,662,664,666,668],{"class":30,"line":100},[28,661,408],{"class":42},[28,663,583],{"class":38},[28,665,575],{"class":62},[28,667,469],{"class":38},[28,669,240],{"class":42},[28,671,672],{"class":30,"line":139},[28,673,674],{"class":181},"\u002F\u002F {id: 1, content: 'changed!'}\n",[28,676,677],{"class":30,"line":178},[28,678,679],{"class":181},"\u002F\u002F contentが変更されている\n",[10,681,682],{},"これが今回起きた原因です。つまり一応スプレッド構文を使用するのは配列の値をコピーするのでは確かに正しいのですが、今回のようなオブジェクトが内包されている場合は別の手法が必要です。",[204,684,201],{"id":201},[10,686,687],{},"さて上記のように配列にオブジェクトが内包されている場合は、オブジェクトの参照が維持されたままになるのは確認できました。ではスプレッド構文以外にどうやって中身を値渡しできるでしょうか？",[10,689,690],{},"この時とられる方法としては「ディープコピー」があります。今回のように配列内のオブジェクトも値渡ししたいとき、つまり配列の中の深いとこまでマルッと別物としてコピーする処理をディープコピーと言います。",[374,692,695,696,699],{"className":693},[377,694],"alert-warning","\nvanilla ES6に",[14,697,698],{},"Array.prototype.deepcopy()","みたいなディープコピーを一発で行う関数はありません。以下の３つテクニックを使用します。\n",[362,701,703],{"id":702},"_1jsonstringifyを使う","1:JSON.stringifyを使う",[10,705,706,707,710,711,714],{},"手取り早いのは",[14,708,709],{},"JSON.stringify()","を使用してコピー元をJSONにして、すぐに",[14,712,713],{},"JSON.parse()","を使用して元に戻します。この際、デコードしたJSONは全く新しい値となるので参照を断ち切ることができます。",[19,716,718],{"className":21,"code":717,"filename":251,"language":23,"meta":24,"style":24},"> const origin =[{id:1,content:\"1111\"},{id:2,content:\"2222\"}];\n\n> const copyjson = JSON.prase(JSON.stringify(origin));\n\n> copyjson;\n\u002F\u002F [{id:1,content:\"1111\"},{id:2,content:\"2222\"}]\n\n> origin === copyjson;\n\u002F\u002F false\n\n> origin[0] === copyjson[0]\n\u002F\u002F false\n\u002F\u002F よし！\n",[14,719,720,778,782,814,818,827,832,836,848,852,856,875,879],{"__ignoreMap":24},[28,721,722,724,726,728,730,732,734,736,738,740,742,744,746,748,750,752,754,756,758,760,762,764,766,768,770,772,774,776],{"class":30,"line":31},[28,723,408],{"class":42},[28,725,411],{"class":34},[28,727,414],{"class":38},[28,729,43],{"class":42},[28,731,419],{"class":38},[28,733,422],{"class":42},[28,735,56],{"class":55},[28,737,59],{"class":42},[28,739,63],{"class":62},[28,741,66],{"class":42},[28,743,85],{"class":55},[28,745,59],{"class":42},[28,747,74],{"class":42},[28,749,439],{"class":77},[28,751,74],{"class":42},[28,753,444],{"class":42},[28,755,56],{"class":55},[28,757,59],{"class":42},[28,759,109],{"class":62},[28,761,66],{"class":42},[28,763,85],{"class":55},[28,765,59],{"class":42},[28,767,74],{"class":42},[28,769,461],{"class":77},[28,771,74],{"class":42},[28,773,466],{"class":42},[28,775,469],{"class":38},[28,777,240],{"class":42},[28,779,780],{"class":30,"line":49},[28,781,246],{"emptyLinePlaceholder":245},[28,783,784,786,788,791,793,796,798,801,804,806,809,812],{"class":30,"line":100},[28,785,408],{"class":42},[28,787,411],{"class":34},[28,789,790],{"class":38}," copyjson ",[28,792,43],{"class":42},[28,794,795],{"class":38}," JSON",[28,797,234],{"class":42},[28,799,800],{"class":256},"prase",[28,802,803],{"class":38},"(JSON",[28,805,234],{"class":42},[28,807,808],{"class":256},"stringify",[28,810,811],{"class":38},"(origin))",[28,813,240],{"class":42},[28,815,816],{"class":30,"line":139},[28,817,246],{"emptyLinePlaceholder":245},[28,819,820,822,825],{"class":30,"line":178},[28,821,408],{"class":42},[28,823,824],{"class":38}," copyjson",[28,826,240],{"class":42},[28,828,829],{"class":30,"line":185},[28,830,831],{"class":181},"\u002F\u002F [{id:1,content:\"1111\"},{id:2,content:\"2222\"}]\n",[28,833,834],{"class":30,"line":280},[28,835,246],{"emptyLinePlaceholder":245},[28,837,838,840,842,844,846],{"class":30,"line":286},[28,839,408],{"class":42},[28,841,414],{"class":38},[28,843,529],{"class":42},[28,845,824],{"class":38},[28,847,240],{"class":42},[28,849,850],{"class":30,"line":292},[28,851,561],{"class":181},[28,853,854],{"class":30,"line":298},[28,855,246],{"emptyLinePlaceholder":245},[28,857,858,860,862,864,866,868,871,873],{"class":30,"line":304},[28,859,408],{"class":42},[28,861,572],{"class":38},[28,863,575],{"class":62},[28,865,578],{"class":38},[28,867,529],{"class":42},[28,869,870],{"class":38}," copyjson[",[28,872,575],{"class":62},[28,874,188],{"class":38},[28,876,877],{"class":30,"line":310},[28,878,561],{"class":181},[28,880,881],{"class":30,"line":316},[28,882,883],{"class":181},"\u002F\u002F よし！\n",[10,885,886],{},"JSONエンコードしてデコードする必要はありますが、中身がなんであろうが関係なく展開できるのは良いところです。",[362,888,890],{"id":889},"_2スプレッドとmapを組み合わせる使用箇所が限定的なので微妙","2:スプレッドとmap()を組み合わせる（使用箇所が限定的なので微妙）",[10,892,893,894,902],{},"スプレッド構文はオブジェクトにも使用できます。しかし今回は配列内にいるのが厄介です。そんな時は ",[193,895,899],{"href":896,"rel":897},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fja\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FArray\u002Fmap",[898],"nofollow",[14,900,901],{},"map()","を使用して各々のオブジェクトを展開して、新しい配列を生成します。",[19,904,906],{"className":21,"code":905,"filename":251,"language":23,"meta":24,"style":24},"> const origin =[{id:1,content:\"1111\"},{id:2,content:\"2222\"}];\n\n> const copymap = origin.map(obj => {return {...obj}});\n\n> copymap;\n\u002F\u002F [{id:1,content:\"1111\"},{id:2,content:\"2222\"}]\n\n> origin === copymap;\n\u002F\u002F false\n\n> origin[0] === copymap[0]\n\u002F\u002F false\n\u002F\u002F よし！\n",[14,907,908,966,970,1018,1022,1031,1035,1039,1051,1055,1059,1078,1082],{"__ignoreMap":24},[28,909,910,912,914,916,918,920,922,924,926,928,930,932,934,936,938,940,942,944,946,948,950,952,954,956,958,960,962,964],{"class":30,"line":31},[28,911,408],{"class":42},[28,913,411],{"class":34},[28,915,414],{"class":38},[28,917,43],{"class":42},[28,919,419],{"class":38},[28,921,422],{"class":42},[28,923,56],{"class":55},[28,925,59],{"class":42},[28,927,63],{"class":62},[28,929,66],{"class":42},[28,931,85],{"class":55},[28,933,59],{"class":42},[28,935,74],{"class":42},[28,937,439],{"class":77},[28,939,74],{"class":42},[28,941,444],{"class":42},[28,943,56],{"class":55},[28,945,59],{"class":42},[28,947,109],{"class":62},[28,949,66],{"class":42},[28,951,85],{"class":55},[28,953,59],{"class":42},[28,955,74],{"class":42},[28,957,461],{"class":77},[28,959,74],{"class":42},[28,961,466],{"class":42},[28,963,469],{"class":38},[28,965,240],{"class":42},[28,967,968],{"class":30,"line":49},[28,969,246],{"emptyLinePlaceholder":245},[28,971,972,974,976,979,981,983,985,988,991,995,998,1001,1005,1008,1010,1013,1016],{"class":30,"line":100},[28,973,408],{"class":42},[28,975,411],{"class":34},[28,977,978],{"class":38}," copymap ",[28,980,43],{"class":42},[28,982,489],{"class":38},[28,984,234],{"class":42},[28,986,987],{"class":256},"map",[28,989,990],{"class":38},"(",[28,992,994],{"class":993},"s7ZW3","obj",[28,996,997],{"class":34}," =>",[28,999,1000],{"class":42}," {",[28,1002,1004],{"class":1003},"s6cf3","return",[28,1006,1007],{"class":42}," {...",[28,1009,994],{"class":38},[28,1011,1012],{"class":42},"}}",[28,1014,1015],{"class":38},")",[28,1017,240],{"class":42},[28,1019,1020],{"class":30,"line":139},[28,1021,246],{"emptyLinePlaceholder":245},[28,1023,1024,1026,1029],{"class":30,"line":178},[28,1025,408],{"class":42},[28,1027,1028],{"class":38}," copymap",[28,1030,240],{"class":42},[28,1032,1033],{"class":30,"line":185},[28,1034,831],{"class":181},[28,1036,1037],{"class":30,"line":280},[28,1038,246],{"emptyLinePlaceholder":245},[28,1040,1041,1043,1045,1047,1049],{"class":30,"line":286},[28,1042,408],{"class":42},[28,1044,414],{"class":38},[28,1046,529],{"class":42},[28,1048,1028],{"class":38},[28,1050,240],{"class":42},[28,1052,1053],{"class":30,"line":292},[28,1054,561],{"class":181},[28,1056,1057],{"class":30,"line":298},[28,1058,246],{"emptyLinePlaceholder":245},[28,1060,1061,1063,1065,1067,1069,1071,1074,1076],{"class":30,"line":304},[28,1062,408],{"class":42},[28,1064,572],{"class":38},[28,1066,575],{"class":62},[28,1068,578],{"class":38},[28,1070,529],{"class":42},[28,1072,1073],{"class":38}," copymap[",[28,1075,575],{"class":62},[28,1077,188],{"class":38},[28,1079,1080],{"class":30,"line":310},[28,1081,561],{"class":181},[28,1083,1084],{"class":30,"line":316},[28,1085,883],{"class":181},[10,1087,1088,1089,1092],{},"JSONを使うよりスマートですが、配列内がオブジェクト・配列といったiterableなものでないと使えません。今使用した",[14,1090,1091],{},"origin","のような簡単な構成であればいいですが、途中で文字列があったりなど、中身が全てiterableである保証がない場合はエラーが起きる可能性があります。あと以下の様にオブジェクトの中にオブジェクトがあるネストした場合はディープコピーできません！！",[19,1094,1096],{"className":21,"code":1095,"filename":251,"language":23,"meta":24,"style":24},"> const origin =[{id:1,content:{summery:\"detail1\",detail:\"detail1\"}},{id:2,content:{summery:\"detail2\",detail:\"detail2\"}},];\n\n> const copymap = origin.map(obj => {return {...obj}});\n\n> origin[0] === copymap[0]\n\u002F\u002F false\n\n> origin[0].content === copymap[0].content;\n\u002F\u002F true\n\u002F\u002F んっっ！？\n",[14,1097,1098,1195,1199,1235,1239,1257,1261,1265,1293,1297],{"__ignoreMap":24},[28,1099,1100,1102,1104,1106,1108,1110,1112,1114,1116,1118,1120,1122,1125,1128,1130,1132,1135,1137,1139,1142,1144,1146,1148,1150,1153,1155,1157,1159,1161,1163,1165,1167,1169,1171,1174,1176,1178,1180,1182,1184,1186,1188,1191,1193],{"class":30,"line":31},[28,1101,408],{"class":42},[28,1103,411],{"class":34},[28,1105,414],{"class":38},[28,1107,43],{"class":42},[28,1109,419],{"class":38},[28,1111,422],{"class":42},[28,1113,56],{"class":55},[28,1115,59],{"class":42},[28,1117,63],{"class":62},[28,1119,66],{"class":42},[28,1121,85],{"class":55},[28,1123,1124],{"class":42},":{",[28,1126,1127],{"class":55},"summery",[28,1129,59],{"class":42},[28,1131,74],{"class":42},[28,1133,1134],{"class":77},"detail1",[28,1136,74],{"class":42},[28,1138,66],{"class":42},[28,1140,1141],{"class":55},"detail",[28,1143,59],{"class":42},[28,1145,74],{"class":42},[28,1147,1134],{"class":77},[28,1149,74],{"class":42},[28,1151,1152],{"class":42},"}},{",[28,1154,56],{"class":55},[28,1156,59],{"class":42},[28,1158,109],{"class":62},[28,1160,66],{"class":42},[28,1162,85],{"class":55},[28,1164,1124],{"class":42},[28,1166,1127],{"class":55},[28,1168,59],{"class":42},[28,1170,74],{"class":42},[28,1172,1173],{"class":77},"detail2",[28,1175,74],{"class":42},[28,1177,66],{"class":42},[28,1179,1141],{"class":55},[28,1181,59],{"class":42},[28,1183,74],{"class":42},[28,1185,1173],{"class":77},[28,1187,74],{"class":42},[28,1189,1190],{"class":42},"}},",[28,1192,469],{"class":38},[28,1194,240],{"class":42},[28,1196,1197],{"class":30,"line":49},[28,1198,246],{"emptyLinePlaceholder":245},[28,1200,1201,1203,1205,1207,1209,1211,1213,1215,1217,1219,1221,1223,1225,1227,1229,1231,1233],{"class":30,"line":100},[28,1202,408],{"class":42},[28,1204,411],{"class":34},[28,1206,978],{"class":38},[28,1208,43],{"class":42},[28,1210,489],{"class":38},[28,1212,234],{"class":42},[28,1214,987],{"class":256},[28,1216,990],{"class":38},[28,1218,994],{"class":993},[28,1220,997],{"class":34},[28,1222,1000],{"class":42},[28,1224,1004],{"class":1003},[28,1226,1007],{"class":42},[28,1228,994],{"class":38},[28,1230,1012],{"class":42},[28,1232,1015],{"class":38},[28,1234,240],{"class":42},[28,1236,1237],{"class":30,"line":139},[28,1238,246],{"emptyLinePlaceholder":245},[28,1240,1241,1243,1245,1247,1249,1251,1253,1255],{"class":30,"line":178},[28,1242,408],{"class":42},[28,1244,572],{"class":38},[28,1246,575],{"class":62},[28,1248,578],{"class":38},[28,1250,529],{"class":42},[28,1252,1073],{"class":38},[28,1254,575],{"class":62},[28,1256,188],{"class":38},[28,1258,1259],{"class":30,"line":185},[28,1260,561],{"class":181},[28,1262,1263],{"class":30,"line":280},[28,1264,246],{"emptyLinePlaceholder":245},[28,1266,1267,1269,1271,1273,1275,1277,1279,1281,1283,1285,1287,1289,1291],{"class":30,"line":286},[28,1268,408],{"class":42},[28,1270,572],{"class":38},[28,1272,575],{"class":62},[28,1274,469],{"class":38},[28,1276,234],{"class":42},[28,1278,641],{"class":38},[28,1280,529],{"class":42},[28,1282,1073],{"class":38},[28,1284,575],{"class":62},[28,1286,469],{"class":38},[28,1288,234],{"class":42},[28,1290,85],{"class":38},[28,1292,240],{"class":42},[28,1294,1295],{"class":30,"line":292},[28,1296,539],{"class":181},[28,1298,1299],{"class":30,"line":298},[28,1300,1301],{"class":181},"\u002F\u002F んっっ！？\n",[10,1303,1304],{},"なのでこのmapとスプレッドは使うのは結構微妙です。",[362,1306,1308],{"id":1307},"_3lodashのclonedeepを使用する","3:lodashのcloneDeep()を使用する",[10,1310,1311,1312,1315,1316,1318],{},"テクニックではないのですがlodashなどのライブラリを用いると、",[14,1313,1314],{},"cloneDeep()","といったディープコピー を行うユーティリティー関数があります。面倒な場合はそれを使ってしまってもいいと思います。なんか方法１のJSONよりもlodashの",[14,1317,1314],{},"の方が早いみたいです。",[10,1320,1321],{},[193,1322,1325],{"href":1323,"rel":1324},"https:\u002F\u002Fqiita.com\u002Fsuin\u002Fitems\u002F80e687dd1789b9d9d2fd",[898],"参考：JavaScriptのディープコピー速さ比較 〜7つの手法\u002Fライブラリを比べてみた〜",[19,1327,1329],{"className":21,"code":1328,"filename":251,"language":23,"meta":24,"style":24},"> const origin =[{id:1,content:{summery:\"detail1\",detail:\"detail1\"}},{id:2,content:{summery:\"detail2\",detail:\"detail2\"}},];\n\n> const copy_ =  _.cloneDeep(origin);\n\n> origin[0] === copy_[0]\n\u002F\u002F false\n\n> origin[0].content === copy_[0].content;\n\u002F\u002F false\n\u002F\u002F よし！\n",[14,1330,1331,1421,1425,1449,1453,1472,1476,1480,1508,1512],{"__ignoreMap":24},[28,1332,1333,1335,1337,1339,1341,1343,1345,1347,1349,1351,1353,1355,1357,1359,1361,1363,1365,1367,1369,1371,1373,1375,1377,1379,1381,1383,1385,1387,1389,1391,1393,1395,1397,1399,1401,1403,1405,1407,1409,1411,1413,1415,1417,1419],{"class":30,"line":31},[28,1334,408],{"class":42},[28,1336,411],{"class":34},[28,1338,414],{"class":38},[28,1340,43],{"class":42},[28,1342,419],{"class":38},[28,1344,422],{"class":42},[28,1346,56],{"class":55},[28,1348,59],{"class":42},[28,1350,63],{"class":62},[28,1352,66],{"class":42},[28,1354,85],{"class":55},[28,1356,1124],{"class":42},[28,1358,1127],{"class":55},[28,1360,59],{"class":42},[28,1362,74],{"class":42},[28,1364,1134],{"class":77},[28,1366,74],{"class":42},[28,1368,66],{"class":42},[28,1370,1141],{"class":55},[28,1372,59],{"class":42},[28,1374,74],{"class":42},[28,1376,1134],{"class":77},[28,1378,74],{"class":42},[28,1380,1152],{"class":42},[28,1382,56],{"class":55},[28,1384,59],{"class":42},[28,1386,109],{"class":62},[28,1388,66],{"class":42},[28,1390,85],{"class":55},[28,1392,1124],{"class":42},[28,1394,1127],{"class":55},[28,1396,59],{"class":42},[28,1398,74],{"class":42},[28,1400,1173],{"class":77},[28,1402,74],{"class":42},[28,1404,66],{"class":42},[28,1406,1141],{"class":55},[28,1408,59],{"class":42},[28,1410,74],{"class":42},[28,1412,1173],{"class":77},[28,1414,74],{"class":42},[28,1416,1190],{"class":42},[28,1418,469],{"class":38},[28,1420,240],{"class":42},[28,1422,1423],{"class":30,"line":49},[28,1424,246],{"emptyLinePlaceholder":245},[28,1426,1427,1429,1431,1434,1436,1439,1441,1444,1447],{"class":30,"line":100},[28,1428,408],{"class":42},[28,1430,411],{"class":34},[28,1432,1433],{"class":38}," copy_ ",[28,1435,43],{"class":42},[28,1437,1438],{"class":38},"  _",[28,1440,234],{"class":42},[28,1442,1443],{"class":256},"cloneDeep",[28,1445,1446],{"class":38},"(origin)",[28,1448,240],{"class":42},[28,1450,1451],{"class":30,"line":139},[28,1452,246],{"emptyLinePlaceholder":245},[28,1454,1455,1457,1459,1461,1463,1465,1468,1470],{"class":30,"line":178},[28,1456,408],{"class":42},[28,1458,572],{"class":38},[28,1460,575],{"class":62},[28,1462,578],{"class":38},[28,1464,529],{"class":42},[28,1466,1467],{"class":38}," copy_[",[28,1469,575],{"class":62},[28,1471,188],{"class":38},[28,1473,1474],{"class":30,"line":185},[28,1475,561],{"class":181},[28,1477,1478],{"class":30,"line":280},[28,1479,246],{"emptyLinePlaceholder":245},[28,1481,1482,1484,1486,1488,1490,1492,1494,1496,1498,1500,1502,1504,1506],{"class":30,"line":286},[28,1483,408],{"class":42},[28,1485,572],{"class":38},[28,1487,575],{"class":62},[28,1489,469],{"class":38},[28,1491,234],{"class":42},[28,1493,641],{"class":38},[28,1495,529],{"class":42},[28,1497,1467],{"class":38},[28,1499,575],{"class":62},[28,1501,469],{"class":38},[28,1503,234],{"class":42},[28,1505,85],{"class":38},[28,1507,240],{"class":42},[28,1509,1510],{"class":30,"line":292},[28,1511,561],{"class":181},[28,1513,1514],{"class":30,"line":298},[28,1515,883],{"class":181},[10,1517,1518],{},"ちなみに方法１のJSONもネストしたオブジェクトの参照は断ち切れます。",[204,1520,1522],{"id":1521},"ライブラリかjson変換を使うといい","ライブラリかJSON変換を使うといい",[10,1524,1525],{},"以上が配列内のオブジェクトの値が連動してしまう原因と対処法です。正確には配列内にオブジェクトを含む場合や、オブジェクト内にオブジェクトを含む値コピーする時は「ディープコピー 」を使いましょうというお話です。ネストしたオブジェクトは今回解説した様に、参照が根深く残っています。アプリによっては以下のような単純な構造でなく、",[19,1527,1529],{"className":21,"code":1528,"language":23,"meta":24,"style":24},"[{id:1,content:\"1111\"},{id:2,content:\"2222\"}];\n",[14,1530,1531],{"__ignoreMap":24},[28,1532,1533,1535,1537,1539,1541,1543,1545,1547,1549,1551,1553,1555,1557,1559,1561,1563,1565,1567,1569,1571,1573,1575,1577,1579],{"class":30,"line":31},[28,1534,419],{"class":38},[28,1536,422],{"class":42},[28,1538,56],{"class":55},[28,1540,59],{"class":42},[28,1542,63],{"class":62},[28,1544,66],{"class":42},[28,1546,85],{"class":55},[28,1548,59],{"class":42},[28,1550,74],{"class":42},[28,1552,439],{"class":77},[28,1554,74],{"class":42},[28,1556,444],{"class":42},[28,1558,56],{"class":55},[28,1560,59],{"class":42},[28,1562,109],{"class":62},[28,1564,66],{"class":42},[28,1566,85],{"class":55},[28,1568,59],{"class":42},[28,1570,74],{"class":42},[28,1572,461],{"class":77},[28,1574,74],{"class":42},[28,1576,466],{"class":42},[28,1578,469],{"class":38},[28,1580,240],{"class":42},[10,1582,1583],{},"以下のように内包する値も複雑で、さらにオブジェクトがネストしていることもあります。",[19,1585,1587],{"className":21,"code":1586,"language":23,"meta":24,"style":24},"const origin = {\n    title: \"...\", \u002F\u002F 途中にiterableでないものがある。\n    todo:[\n            {\n                id:1,\n                \u002F\u002F オブジェクトがネストしている\n                content:{\n                    summery:\"detail1\",detail:\"detail1\"\n                }\n            },\n            {\n                id:2,\n                content:{\n                    summery:\"detail2\",detail:\"detail2\"\n                }\n            }\n        ];\n    \u002F\u002F More unpredictable properties..\n}\n",[14,1588,1589,1600,1618,1628,1633,1645,1650,1658,1684,1689,1694,1698,1708,1714,1738,1742,1747,1753,1759],{"__ignoreMap":24},[28,1590,1591,1593,1595,1597],{"class":30,"line":31},[28,1592,35],{"class":34},[28,1594,414],{"class":38},[28,1596,43],{"class":42},[28,1598,1599],{"class":42}," {\n",[28,1601,1602,1605,1607,1609,1611,1613,1615],{"class":30,"line":49},[28,1603,1604],{"class":55},"    title",[28,1606,59],{"class":42},[28,1608,646],{"class":42},[28,1610,92],{"class":77},[28,1612,74],{"class":42},[28,1614,66],{"class":42},[28,1616,1617],{"class":181}," \u002F\u002F 途中にiterableでないものがある。\n",[28,1619,1620,1623,1625],{"class":30,"line":100},[28,1621,1622],{"class":55},"    todo",[28,1624,59],{"class":42},[28,1626,1627],{"class":38},"[\n",[28,1629,1630],{"class":30,"line":139},[28,1631,1632],{"class":42},"            {\n",[28,1634,1635,1638,1640,1642],{"class":30,"line":178},[28,1636,1637],{"class":55},"                id",[28,1639,59],{"class":42},[28,1641,63],{"class":62},[28,1643,1644],{"class":42},",\n",[28,1646,1647],{"class":30,"line":185},[28,1648,1649],{"class":181},"                \u002F\u002F オブジェクトがネストしている\n",[28,1651,1652,1655],{"class":30,"line":280},[28,1653,1654],{"class":55},"                content",[28,1656,1657],{"class":42},":{\n",[28,1659,1660,1663,1665,1667,1669,1671,1673,1675,1677,1679,1681],{"class":30,"line":286},[28,1661,1662],{"class":55},"                    summery",[28,1664,59],{"class":42},[28,1666,74],{"class":42},[28,1668,1134],{"class":77},[28,1670,74],{"class":42},[28,1672,66],{"class":42},[28,1674,1141],{"class":55},[28,1676,59],{"class":42},[28,1678,74],{"class":42},[28,1680,1134],{"class":77},[28,1682,1683],{"class":42},"\"\n",[28,1685,1686],{"class":30,"line":292},[28,1687,1688],{"class":42},"                }\n",[28,1690,1691],{"class":30,"line":298},[28,1692,1693],{"class":42},"            },\n",[28,1695,1696],{"class":30,"line":304},[28,1697,1632],{"class":42},[28,1699,1700,1702,1704,1706],{"class":30,"line":310},[28,1701,1637],{"class":55},[28,1703,59],{"class":42},[28,1705,109],{"class":62},[28,1707,1644],{"class":42},[28,1709,1710,1712],{"class":30,"line":316},[28,1711,1654],{"class":55},[28,1713,1657],{"class":42},[28,1715,1716,1718,1720,1722,1724,1726,1728,1730,1732,1734,1736],{"class":30,"line":322},[28,1717,1662],{"class":55},[28,1719,59],{"class":42},[28,1721,74],{"class":42},[28,1723,1173],{"class":77},[28,1725,74],{"class":42},[28,1727,66],{"class":42},[28,1729,1141],{"class":55},[28,1731,59],{"class":42},[28,1733,74],{"class":42},[28,1735,1173],{"class":77},[28,1737,1683],{"class":42},[28,1739,1740],{"class":30,"line":328},[28,1741,1688],{"class":42},[28,1743,1744],{"class":30,"line":334},[28,1745,1746],{"class":42},"            }\n",[28,1748,1750],{"class":30,"line":1749},17,[28,1751,1752],{"class":38},"        ];\n",[28,1754,1756],{"class":30,"line":1755},18,[28,1757,1758],{"class":181},"    \u002F\u002F More unpredictable properties..\n",[28,1760,1762],{"class":30,"line":1761},19,[28,1763,331],{"class":42},[10,1765,1766],{},"上記のような状況を踏まえると、ディープコピー はJSONを用いるか大人しくライブラリを使用する方が賢明そうです。値が連動してしまう時はまず値渡し・参照渡しを疑い、その次はディープコピーがされているか（ネストしたオブジェクトがないか）を確かめてみましょう。",[1768,1769,1770],"style",{},"html pre.shiki code .sJ14y, html code.shiki .sJ14y{--shiki-default:#C792EA}html pre.shiki code .s0W1g, html code.shiki .s0W1g{--shiki-default:#BABED8}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html pre.shiki code .s-wAU, html code.shiki .s-wAU{--shiki-default:#F07178}html pre.shiki code .sx098, html code.shiki .sx098{--shiki-default:#F78C6C}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sC9rS, html code.shiki .sC9rS{--shiki-default:#464B5D;--shiki-default-font-style:italic}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s7ZW3, html code.shiki .s7ZW3{--shiki-default:#BABED8;--shiki-default-font-style:italic}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}",{"title":24,"searchDepth":100,"depth":100,"links":1772},[1773,1776,1777,1782],{"id":206,"depth":49,"text":206,"children":1774},[1775],{"id":364,"depth":100,"text":365},{"id":196,"depth":49,"text":196},{"id":201,"depth":49,"text":201,"children":1778},[1779,1780,1781],{"id":702,"depth":100,"text":703},{"id":889,"depth":100,"text":890},{"id":1307,"depth":100,"text":1308},{"id":1521,"depth":49,"text":1522},[1784],"ministack","2021-11-07","配列内のオブジェクトの値が連動するときの原因と対処法","md",null,{},"\u002Farticles\u002Fjs-deep-copy",{"title":5,"description":1786},"articles\u002Fjs-deep-copy",[1794,1795],"js","vue","TVfFMZbaj-eg5y8hB-QhEPtPjdhOPFn6vmaY0JeSo0g",1780987144373]