3750 Stimmen

Wie kann ich ein JavaScript-Objekt korrekt klonen?

Ich habe ein Objekt x . Ich würde es gerne als Objekt kopieren y , so dass Änderungen an y nicht verändern x . Ich habe festgestellt, dass das Kopieren von Objekten, die von integrierten JavaScript-Objekten abgeleitet sind, zu zusätzlichen, unerwünschten Eigenschaften führt. Das ist kein Problem, da ich eines meiner eigenen, wörtlich konstruierten Objekte kopiere.

Wie kann ich ein JavaScript-Objekt korrekt klonen?

35 Stimmen

0 Stimmen

Unterstützen Sie auf jeden Fall @Niyaz! Shortlink: tinyurl.com/JSCopyObject

290 Stimmen

Für JSON verwende ich mObj=JSON.parse(JSON.stringify(jsonObject));

6voto

user1547016 Punkte 79
function clone(src, deep) {

    var toString = Object.prototype.toString;
    if(!src && typeof src != "object"){
        //any non-object ( Boolean, String, Number ), null, undefined, NaN
        return src;
    }

    //Honor native/custom clone methods
    if(src.clone && toString.call(src.clone) == "[object Function]"){
        return src.clone(deep);
    }

    //DOM Elements
    if(src.nodeType && toString.call(src.cloneNode) == "[object Function]"){
        return src.cloneNode(deep);
    }

    //Date
    if(toString.call(src) == "[object Date]"){
        return new Date(src.getTime());
    }

    //RegExp
    if(toString.call(src) == "[object RegExp]"){
        return new RegExp(src);
    }

    //Function
    if(toString.call(src) == "[object Function]"){
        //Wrap in another method to make sure == is not true;
        //Note: Huge performance issue due to closures, comment this :)
        return (function(){
            src.apply(this, arguments);
        });

    }

    var ret, index;
    //Array
    if(toString.call(src) == "[object Array]"){
        //[].slice(0) would soft clone
        ret = src.slice();
        if(deep){
            index = ret.length;
            while(index--){
                ret[index] = clone(ret[index], true);
            }
        }
    }
    //Object
    else {
        ret = src.constructor ? new src.constructor() : {};
        for (var prop in src) {
            ret[prop] = deep
                ? clone(src[prop], true)
                : src[prop];
        }
    }

    return ret;
};

3 Stimmen

if(!src && typeof src != "object"){ . Ich denke, das sollte sein || pas && .

6voto

Bert Regelink Punkte 2646

Desde mindeavor dass das zu klonende Objekt ein 'literal-constructed' Objekt ist, könnte eine Lösung darin bestehen, einfach erzeugen das Objekt mehrfach zu klonen, anstatt eine Instanz des Objekts zu klonen:

function createMyObject()
{
    var myObject =
    {
        ...
    };
    return myObject;
}

var myObjectInstance1 = createMyObject();
var myObjectInstance2 = createMyObject();

5voto

Andy Burke Punkte 67

Die obige Antwort von Jan Turon kommt der Sache sehr nahe und ist aufgrund von Kompatibilitätsproblemen möglicherweise am besten in einem Browser zu verwenden, führt aber möglicherweise zu einigen seltsamen Aufzählungsproblemen. Zum Beispiel, Ausführen:

for ( var i in someArray ) { ... }

Weist i nach der Iteration durch die Elemente des Arrays die Methode clone() zu. Hier ist eine Anpassung, die die Aufzählung vermeidet und mit node.js funktioniert:

Object.defineProperty( Object.prototype, "clone", {
    value: function() {
        if ( this.cloneNode )
        {
            return this.cloneNode( true );
        }

        var copy = this instanceof Array ? [] : {};
        for( var attr in this )
        {
            if ( typeof this[ attr ] == "function" || this[ attr ] == null || !this[ attr ].clone )
            {
                copy[ attr ] = this[ attr ];
            }
            else if ( this[ attr ] == this )
            {
                copy[ attr ] = copy;
            }
            else
            {
                copy[ attr ] = this[ attr ].clone();
            }
        }
        return copy;
    }
});

Object.defineProperty( Date.prototype, "clone", {
    value: function() {
        var copy = new Date();
        copy.setTime( this.getTime() );
        return copy;
    }
});

Object.defineProperty( Number.prototype, "clone", { value: function() { return this; } } );
Object.defineProperty( Boolean.prototype, "clone", { value: function() { return this; } } );
Object.defineProperty( String.prototype, "clone", { value: function() { return this; } } );

Dadurch wird vermieden, dass die Methode clone() aufzählbar ist, da defineProperty() enumerable standardmäßig auf false setzt.

5voto

GANESH CHOKHARE Punkte 186

Objektkopie mit ( ... )

//bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2,c: 3 }

//good
const originalObj = { id: 5, name: 'San Francisco'};
const copyObject = {...originalObj, pincode: 4444};
console.log(copyObject)  //{ id: 5, name: 'San Francisco', pincode: 4444 }

Dasselbe kann verwendet werden für Kopieren von Array von einem zum anderen

const itemsCopy = [...items];

0 Stimmen

Warum ist Object.assign way als "schlecht" eingestuft? Könnte das jemand näher erläutern?

5voto

Raskolnikov Punkte 91

Einfache rekursive Methode zum Klonen eines Objekts. Man könnte auch lodash.clone verwenden.

let clone = (obj) => {
    let obj2 = Array.isArray(obj) ? [] : {};
    for(let k in obj) {
          obj2[k] = (typeof obj[k] === 'object' ) ? clone(obj[k]) :  obj[k];
        }
        return obj2;
    }

let w = { name: "Apple", types: ["Fuji", "Gala"]};
let x = clone(w);
w.name = "Orange";
w.types = ["Navel"];
console.log(x);
console.log(w);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X