La différence entre la copie profonde et la copie superficielle d'un objet est la suivante :
Copie superficielle : copie uniquement la référence de l'objet, pas l'objet lui-même
Copie approfondie : copie tous les objets ; référencé par l'objet copié. Copiez-le à nouveau.
1. Implémentation de la copie superficielle
La méthode d'implémentation de la copie superficielle est relativement simple, à condition d'utiliser une simple instruction de copie.
1.1 Méthode 1 : Instruction de copie simple
/* ================ 浅拷贝 ================ */ function simpleClone(initalObj) { var obj = {}; for ( var i in initalObj) { obj[i] = initalObj[i]; } return obj; }
Appel client
/* ================ 客户端调用 ================ */ 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"); } // 原对象所引用的函数未被修改
1.2 Méthode 2 : Object.assign()
L'objet La méthode .assign() peut copier n'importe quel nombre de propriétés énumérables de l'objet source vers l'objet cible, puis renvoyer l'objet cible. Cependant, Object.assign() effectue une copie superficielle, en copiant les références aux propriétés de l'objet, et non à l'objet lui-même.
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
2. Implémentation de la copie profonde
Il existe de nombreuses façons d'implémenter la copie profonde, y compris la méthode JSON.parse() la plus simple et la méthode de copie récursive couramment utilisée, et dans Méthode ES5 Object.create().
2.1 Méthode 1 : Utilisez la méthode JSON.parse()
Il existe de nombreuses façons d'implémenter la copie approfondie. Par exemple, la méthode la plus simple consiste à utiliser 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"
Cette méthode est simple et facile à utiliser.
Mais cette méthode présente également de nombreux inconvénients, par exemple, elle supprimera le constructeur de l'objet. C'est-à-dire qu'après une copie profonde, quel que soit le constructeur d'origine de l'objet, il deviendra Objet après une copie profonde.
Les seuls objets que cette méthode peut gérer correctement sont les objets Number, String, Boolean, Array et plats, c'est-à-dire les structures de données qui peuvent être directement représentées par json. Les objets RegExp ne peuvent pas être copiés en profondeur de cette manière.
2.2 Méthode 2 : Copie récursive
Le code est le suivant :
/* ================ 深拷贝 ================ */ 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; }
Le code ci-dessus peut en effet réaliser une copie profonde. Mais lorsque vous rencontrez deux objets qui se référencent l’un à l’autre, une boucle infinie se produit.
Afin d'éviter une boucle infinie provoquée par des objets se référençant les uns aux autres, vous devez déterminer si les objets se font référence les uns aux autres pendant le parcours, et si c'est le cas, quitter la boucle.
Le code amélioré est le suivant :
/* ================ 深拷贝 ================ */ 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 Méthode 3 : Utilisez la méthode Object.create()
Utilisez var newObj = Object.create(oldObj) directement, vous pouvez obtenir l'effet de copie complète.
/* ================ 深拷贝 ================ */ 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. Référence : Implémentation de la méthode jQuery.extend()
jQuery.extend() de jQuery.js implémente également la copie approfondie des objets. Le code officiel est affiché ci-dessous pour référence.
Adresse du lien officiel : 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; };
Cet article présente principalement le contenu de js sur la copie profonde. Pour d'autres contenus, vous pouvez consulter les articles précédemment publiés par le site Web chinois PHP
Plus d'articles liés à la copie profonde de. objets en JavaScript Veuillez faire attention au site Web chinois PHP !