---
# System prepended metadata

title: Duplicate Array

---

# Duplicate Array
## 前言: Pass 賦值
#### 一般情況： 
|  | 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