Maison > interface Web > js tutoriel > Copie profonde d'objets en JavaScript

Copie profonde d'objets en JavaScript

高洛峰
Libérer: 2017-01-03 16:07:06
original
1023 Les gens l'ont consulté

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;
}
Copier après la connexion

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"); } // 原对象所引用的函数未被修改
Copier après la connexion

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"
Copier après la connexion

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;
}
Copier après la connexion
/* ================ 客户端调用 ================ */
var obj = {
    a: {
        a: "world",
        b: 21
    }
}
var cloneObj = deepClone(obj);
cloneObj.a.a = "changed";
  
console.log(obj.a.a); // "world"
Copier après la connexion

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;
}
Copier après la connexion

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;
}
Copier après la connexion

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;
}
Copier après la connexion

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&#39;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&#39;t bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }
  
    // Return the modified object
    return target;
};
Copier après la connexion

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 !

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal