# 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