# clone(obj)

{% tabs %}
{% tab title="💾 程式" %}
* replit ⟩ [JS ⟩ object ⟩ clone()](https://replit.com/@pegasusroe/JS-object-clone#index.js)

```javascript
// truly exact copy of `obj`, including all properties: 
// • enumerable and non-enumerable
// • data properties, setters/getters
// with the right [[Prototype]].
function clone(obj) {
    return Object.create(
        Object.getPrototypeOf(obj),                // same [[Prototype]] as obj.
        Object.getOwnPropertyDescriptors(obj)      // clone all own members.
    );
}
```

💈範例：

{% hint style="danger" %}
雖然可以用 clone() 複製物件，但兩個物件之間，依然有可能存在些微差異，例如：下例的 a 是一個 Array，但 clone() 之後的 a2 就不是 Array❗️
{% endhint %}

```javascript
// an array
let a = [1,2,3];

// an object
const o = {
    name: 'Joe',
    age: 25,
    array: [1,2,3],
    hobbies: {
        sports: ['badminton', 'baseball'],
        games: ['zelda', 'poker']
    }
}

// clone
let a2 = clone(a);
let o2 = clone(o);

// change some properties
o.array = [];                // ⭐ now, `o.array !== o2.array`❗
o.hobbies.games = [];        // ⭐ since `o.hobbies === o2.hobbies`,
                             //   `o.hobbies.games === o2.hobbies.games`❗

// ---------------------- console ----------------------------------
[
    a,                       // [ 1, 2, 3 ]
    typeof a,                // 'object'
    Array.isArray(a),        // true
    
    a2,                      // Array { '0': 1, '1': 2, '2': 3 }
    typeof a2,               // 'object'
    Array.isArray(a2),       // false (a2 is NOT an array❗)

    JSON.stringify(o),
    // {
    //     name: "Joe",
    //     age : 25,
    //     array  : [],      // ⭐ `o.array` overwritten❗
    //     hobbies: {
    //         sports:["badminton","baseball"],
    //         games :[]     // ⭐ this one has changed.
    //     }
    // }
    
    JSON.stringify(o2),
    // {
    //     name: "Joe",
    //     age : 25,
    //     array  : [1,2,3], // ⭐ `o2.array` remains intact.
    //     hobbies: {
    //         sports:["badminton","baseball"],
    //         games :[]     // ⭐ this (same) one has changed too.
    //     }
    // }
    
].forEach(x => log(x));
```
{% endtab %}

{% tab title="💾 比較" %}
```javascript
let arr = [1, 2, 3];

// ⭐️ shallow copy
let copy = [...arr];        // "spread" operator
let copy = arr.slice()      // Array method

// ⭐️ deep copy
let deepcopy = JSON.parse(JSON.stringify(arr));
```
{% endtab %}

{% tab title="📗 參考" %}
* [ ] JS.info ⟩ [Prototype methods, objects without **\_\_proto\_\_**](https://javascript.info/prototype-methods)
{% endtab %}

{% tab title="📘 手冊" %}
* [Object.create()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)
* [Object.getPrototypeOf()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf)
* [Object.getOwnPropertyDescriptors()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptors)
* Object.assign ⟩ [Cloning an object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#cloning_an_object)
* [Deep copy](https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy)
{% endtab %}

{% tab title="👥 相關" %}
* [proto](../../../js/val/obj/proto "mention") is also cloned.
* cloning is similar to [mixin](../../../js/val/obj/extend/mixin "mention").
{% endtab %}
{% endtabs %}
