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 < in ES5 🎜> 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"
, 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; }
/* ================ 深拷贝 ================ */ 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; }
/* ================ 深拷贝 ================ */ 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; }
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; };