Heim >Web-Frontend >js-Tutorial >Detaillierte Einführung in das tiefe Kopieren von Objekten in JavaScript
In JavaScript ist es üblich, Objekte zu kopieren. Eine einfache Kopieranweisung kann jedoch nur eine flache Kopie eines Objekts erstellen, d. h. es wird eine Referenz kopiert, nicht das Objekt, auf das sie verweist. Häufiger möchten wir eine tiefe Kopie des Objekts erstellen, um zu verhindern, dass das Originalobjekt unbeabsichtigt geändert wird.
Der Unterschied zwischen tiefer Kopie und flacher Kopie eines Objekts ist wie folgt:
Flache Kopie: kopiert nur die Referenz des Objekts, nicht das Objekt selbst
Tiefe Kopie: Kopiert alle Objekte, auf die das kopierte Objekt verweist.
Die Implementierungsmethode einer flachen Kopie ist relativ einfach, solange eine einfache Kopieranweisung verwendet wird.
/* ================ 浅拷贝 ================ */ function simpleClone(initalObj) { var obj = {}; for ( var i in initalObj) { obj[i] = initalObj[i]; } return obj; }
/* ================ 客户端调用 ================ */ var obj = { a: "hello", b: { a: "world", b: 21 }, c: ["Bob", "Tom", "Jenny"], d: function() { alert("hello world"); } } var cloneObj = simpleClone(obj); // 对象拷贝 console.log(cloneObj.b); // {a: "world", b: 21} console.log(cloneObj.c); // ["Bob", "Tom", "Jenny"] console.log(cloneObj.d); // function() { alert("hello world"); } // 修改拷贝后的对象 cloneObj.b.a = "changed"; cloneObj.c = [1, 2, 3]; cloneObj.d = function() { alert("changed"); }; console.log(obj.b); // {a: "changed", b: 21} // // 原对象所引用的对象被修改了 console.log(obj.c); // ["Bob", "Tom", "Jenny"] // 原对象所引用的对象未被修改 console.log(obj.d); // function() { alert("hello world"); } // 原对象所引用的函数未被修改
Object.assign()
Methode kann eine beliebige Anzahl von The zuweisen Die eigenen aufzählbaren Eigenschaften des Quellobjekts werden in das Zielobjekt kopiert und dann wird das Zielobjekt zurückgegeben. Aber Object.assign()
führt eine flache Kopie durch und kopiert Verweise auf die Eigenschaften des Objekts, nicht das Objekt selbst.
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
Es gibt viele Möglichkeiten, Deep Copy zu implementieren, einschließlich der einfachsten JSON.parse()
-Methode, der häufig verwendeten rekursiven Kopiermethode und der Methode. Object.create()
JSON.parse()
: JSON.parse()
/* ================ 深拷贝 ================ */ function deepClone(initalObj) { var obj = {}; try { obj = JSON.parse(JSON.stringify(initalObj)); } return obj; }
/* ================ 客户端调用 ================ */ var obj = { a: { a: "world", b: 21 } } var cloneObj = deepClone(obj); cloneObj.a.a = "changed"; console.log(obj.a.a); // "world"Diese Methode ist einfach und leicht anzuwenden. Aber diese Methode hat auch viele Nachteile, zum Beispiel wird der Konstruktor des Objekts verworfen. Das heißt, nach dem tiefen Kopieren wird das Objekt unabhängig vom ursprünglichen Konstruktor des Objekts nach dem tiefen Kopieren zum Objekt. Die einzigen Objekte, die diese Methode korrekt verarbeiten kann, sind
, also die Datenstrukturen, die direkt durch JSON dargestellt werden können. RegExp-Objekte können auf diese Weise nicht tief kopiert werden. Number, String, Boolean, Array, 扁平对象
/* ================ 深拷贝 ================ */ function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { if (typeof initalObj[i] === 'object') { obj[i] = (initalObj[i].constructor === Array) ? [] : {}; arguments.callee(initalObj[i], obj[i]); } else { obj[i] = initalObj[i]; } } return obj; }Der obige Code kann tatsächlich eine tiefe Kopie erreichen. Wenn man jedoch auf zwei Objekte stößt, die aufeinander verweisen, entsteht eine Endlosschleife. Um eine Endlosschleife zu vermeiden, die dadurch verursacht wird, dass Objekte aufeinander verweisen, sollten Sie beim Durchlaufen feststellen, ob Objekte aufeinander verweisen, und wenn ja, die Schleife verlassen. Der verbesserte Code lautet wie folgt:
/* ================ 深拷贝 ================ */ function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : {}; arguments.callee(prop, obj[i]); } else { obj[i] = prop; } } return obj; }2.3 Methode 3: Verwenden Sie die Methode Object.create() Verwenden Sie var newObj = Object.create(oldObj) Direkt können Sie den Effekt einer tiefen Kopie erzielen.
/* ================ 深拷贝 ================ */ function deepClone(initalObj, finalObj) { var obj = finalObj || {}; for (var i in initalObj) { var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) { continue; } if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : Object.create(prop); } else { obj[i] = prop; } } return obj; }3. Referenz: Implementierung der jQuery.extend()-Methode jQuery.extend() von jQuery.js implementiert auch eine tiefe Kopie von Objekten. Der offizielle Code wird unten als Referenz veröffentlicht. Offizielle Linkadresse: https://github.com/jquery/jquery/blob/master/src/core.js.
jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[ 0 ] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; // Skip the boolean and the target target = arguments[ i ] || {}; i++; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { target = {}; } // Extend jQuery itself if only one argument is passed if ( i === length ) { target = this; i--; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject( copy ) || ( copyIsArray = jQuery.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray( src ) ? src : []; } else { clone = src && jQuery.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; };Das Obige ist eine detaillierte Einführung in das tiefe Kopieren von Objekten in JavaScript. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!