# Duplicate Array ###### tags: `JavaScript` ## 前言: Pass 賦值 > Everything in JavaScript is either primitive or object. #### 一般情況: | | Pass By Value | Pass By Reference | | -------- | -------- | -------- | | 說明 | 在記憶體中建立一個新位置,賦予數值。 | 指定到物件到 b 到 a 的位置,取得值。 | | 賦值類別 | **`Primitive Type`** 原始型別 | **`Object Type`** 物件型別 類別細節 | Boolean, String, Number, null, undefined | Object, Function, Array, Set #### 例外情況:Pass By Sharing - **函數傳遞(物件)參數** ```javascript= function rename(obj){ obj.name="淑芬"; } var person = { name: "春嬌"}; console.log(person); //春嬌 rename(person); console.log(person); //淑芬 ``` ```javascript= function rename(obj){ obj = { name: "淑芬" }; //{ name: "春嬌" } = { name: "淑芬" } } var person = { name: "春嬌" }; console.log(person); //春嬌 rename(person); console.log(person); //春嬌 ``` - **Array Literals & Object Literals** ```javascript= /* array literals */ var ary1 = [1, 2, 3]; var ary2 = ary1; console.log(ary1); // [1, 2, 3] console.log(ary2); // [1, 2, 3] ary1 = [99, 100]; console.log(ary1); // [99, 100] console.log(ary2); // [1, 2, 3] /* object literals */ var person1 = { money: 111 }; var person2 = person1; console.log(person1); // {money: 111} console.log(person2); // {money: 111} person1 = { money: 222 }; console.log(person1); // {money: 222} console.log(person2); // {money: 111} ``` >因此有些人主張,JavaScript其實是Pass By Sharing,另有一派主張全部都是Pass By Value。 **確定的事實:** > 1. 碰到原生型別 (Primitive),表現行為是 Pass by value。 > 2. 碰到物件型別 (Object),如果只是對物件內容作操作(例如陣列元素或物件屬性),表現行為是 Pass by reference。 > 3. 碰到物件型別 (Object),如果對物件作**重新賦值**,表現行為是 Pass by value。 > [color=#F2B42D] ## 深拷貝 & 淺拷貝 **==淺拷貝 Shallow Copy:==** 複製到同一個參考位置(共用同一個記憶體位址) - ary.slice(0) - ary.concat() - [...ary] - Object.assign() ```javascript= //ary.slice(0) let ary = [1, 2, 3] let newAry = ary.slice(0) //ary.concat() let ary = [1, 2, 3] let newAry = ary.concat() //... let ary = [1, 2, 3] let newAry = [...ary] //Object.assign() let ary = [[1,1], [2,2]] let newAry = Object.assign([],ary) ``` **==深拷貝 Deep Copy:==** 複製整個值包含至深層,存進獨立的記憶體位置,不影響本來的參考。 - JSON.stringify() + JSON.parse() ```javascript= let obj = { A: 1, B: { a: '2-1', b: '2-2' }, C: { a: '3-1', b: '3-2' } } let newObj = JSON.parse(JSON.stringify(obj)) ``` > 基本上原生的 JS 深拷貝只能透過 json 轉字串的這個方法,但這個作法的**效能不是很好**,因此當需要大量使用深拷貝時會使用 lodash 的 cloneDeep... 等等的函式庫。 > 而且 JSON.parse(JSON.stringify(obj)) 是沒辦法拷貝到物件裡的fnction的喔!(需要套件) >深淺拷貝沒有好壞之分,純粹看需要的情境適合那個方法 🙂 **常見的複製方法 & 範圍:** | 方法 | 一維陣列 | 多維陣列 | 單層物件 | 多層物件 | | -------- | -------- | -------- |-------- | -------- | | ary.slice(0) | O | X |X | X | | ary.concat() | O | X |X | X | | Array.from(ary) | O | O |X | X | | [...ary] {...obj} | O | O |O | X | | Object.assign() | O | O |O | X | | JSON.parse(JSON.stringify()) | O | O | O | O | ## 參考資料 https://ithelp.ithome.com.tw/articles/10209104 https://eudora.cc/posts/210430/#%E5%B0%8D-array-object-%E8%A4%87%E8%A3%BD-%E5%80%BC-%E7%9A%84%E5%B9%BE%E7%A8%AE%E5%B8%B8%E8%A6%8B%E6%96%B9%E6%B3%95 https://ithelp.ithome.com.tw/articles/10221481?sc=rss.iron https://pjchender.blogspot.com/2016/03/javascriptby-referenceby-value.html