Maison  >  Article  >  interface Web  >  Explication détaillée de la copie profonde javascript (deepClone)

Explication détaillée de la copie profonde javascript (deepClone)

高洛峰
高洛峰original
2017-01-03 15:59:291140parcourir

La copie profonde Javascript est un problème que les développeurs débutants et même expérimentés rencontrent souvent et ne peuvent pas bien comprendre la copie profonde JavaScript.

Copie profonde (deepClone) ?

Le contraire de la copie profonde est la copie superficielle. De nombreux débutants sont très confus lorsqu'ils entrent en contact avec ce concept.

Pourquoi utiliser la copie profonde ?

Dans de nombreux cas, nous devons attribuer une valeur à une variable et attribuer une valeur à l'adresse mémoire. Cependant, lors de l'attribution d'un type de valeur de référence, celle-ci ne partage qu'une zone mémoire, ce qui entraîne le résultat. affectation. La valeur précédente reste cohérente.

Regardez un exemple spécifique

// 给test赋值了一个对象
var test = {
  a: 'a',
  b: 'b'
};
 
// 将test赋值给test2
// 此时test和test2是共享了同一块内存对象,这也就是浅拷贝
var test2 = test;
 
test2.a = 'a2';
 
test.a === 'a2'// 为true

Illustration :


Vous pouvez maintenant facilement comprendre pourquoi les données de type valeur de référence s'affectent les unes les autres.

Pour implémenter

Pour implémenter une fonction de copie profonde, il faut parler du type numérique de JavaScript.

Type javascript du juge

Il existe les types de base suivants en javascript

Description du type
indéfini Le type indéfini n'a qu'une seule valeur, indéfinie, qui est lorsque la variable n'a pas reçu de valeur La valeur de
null type null n'a également qu'une seule valeur null, qui est une référence d'objet vide
Boolean Boolean a deux valeurs true et false
String Il représente informations textuelles
Nombre Il représente des informations numériques
Objet Il s'agit d'une collection non ordonnée d'une série d'attributs, y compris la fonction et le tableau Array
En utilisant typeof, il est impossible de juger la fonction et le tableau. La méthode toString est utilisée ici.
[Par défaut, chaque objet héritera de la méthode toString() de Object. Si cette méthode n'est pas remplacée (masquée) par la méthode du même nom sur l'objet lui-même ou un prototype supérieur plus proche, la méthode toString() de l'objet le sera. renvoie "[object type]", où le type de chaîne représente un type d'objet][1]

function type(obj) {
  var toString = Object.prototype.toString;
  var map = {
    '[object Boolean]' : 'boolean', 
    '[object Number]'  : 'number', 
    '[object String]'  : 'string', 
    '[object Function]' : 'function', 
    '[object Array]'  : 'array', 
    '[object Date]'   : 'date', 
    '[object RegExp]'  : 'regExp', 
    '[object Undefined]': 'undefined',
    '[object Null]'   : 'null', 
    '[object Object]'  : 'object'
  };
  return map[toString.call(obj)];
}

implémente deepClone

pour les non-Valeurs des types de valeur de référence sont affectés directement, tandis que les types de valeur de référence (objet) doivent être parcourus à nouveau et attribués de manière récursive.

function deepClone(data) {
  var t = type(data), o, i, ni;
   
  if(t === 'array') {
    o = [];
  }else if( t === 'object') {
    o = {};
  }else {
    return data;
  }
   
  if(t === 'array') {
    for (i = 0, ni = data.length; i < ni; i++) {
      o.push(deepClone(data[i]));
    }
    return o;
  }else if( t === &#39;object&#39;) {
    for( i in data) {
      o[i] = deepClone(data[i]);
    }
    return o;
  }
}

Il y a quelque chose auquel vous devez faire attention ici. Pour le type de fonction, le blogueur attribue ici la valeur directement ou partage une valeur mémoire. En effet, la fonction consiste davantage à remplir certaines fonctions, à avoir une valeur d'entrée et une valeur de retour, et pour l'entreprise de niveau supérieur, il s'agit davantage de compléter des fonctions commerciales, et il n'est pas nécessaire de copier en profondeur la fonction.

Mais comment copier le type de fonction ?

En fait, le blogueur n'a pensé qu'à utiliser new pour le faire fonctionner, mais la fonction sera exécutée une fois. Je ne peux pas imaginer quels seront les résultats de l'exécution ! o(╯□╰)o! Je n’ai pas encore d’autres bonnes idées, donc les conseils de chacun sont les bienvenus !

À ce stade, la copie profonde a presque été implémentée. Quelqu'un pense-t-il que la copie superficielle n'a pas encore été implémentée ?

Copie superficielle ?

Pour une copie superficielle, cela peut être compris comme n'exploitant qu'une zone mémoire commune ! Il y aura du danger ici ! (.﹏.*)

Si vous exploitez directement ces données partagées sans contrôle, des anomalies de données se produiront souvent et seront modifiées par d'autres parties. Par conséquent, vous ne devez pas exploiter directement la source de données, mais encapsuler certaines méthodes permettant à la source de données d'effectuer des opérations CURD sur les données.

C'est probablement presque terminé ici, mais en tant que front-end, non seulement JavaScript lui-même doit être pris en compte, mais aussi DOM, navigateur, etc.

Type d'élément

Regardez le code suivant, qu'est-ce qui sera retourné ?

Object.prototype.toString.call(document.getElementsByTagName('div')[0])

La réponse est [object HTMLDivElement]

Parfois enregistrer Si vous copiez accidentellement l'élément DOM, la fonction de copie approfondie ci-dessus ne parviendra pas à juger l'élément Element. Pour juger l’élément Element, utilisez instanceof pour juger. Car pour différentes balises, tostring renverra le constructeur correspondant aux différentes balises.

function type(obj) {
  var toString = Object.prototype.toString;
  var map = {
    &#39;[object Boolean]&#39; : &#39;boolean&#39;, 
    &#39;[object Number]&#39;  : &#39;number&#39;, 
    &#39;[object String]&#39;  : &#39;string&#39;, 
    &#39;[object Function]&#39; : &#39;function&#39;, 
    &#39;[object Array]&#39;  : &#39;array&#39;, 
    &#39;[object Date]&#39;   : &#39;date&#39;, 
    &#39;[object RegExp]&#39;  : &#39;regExp&#39;, 
    &#39;[object Undefined]&#39;: &#39;undefined&#39;,
    &#39;[object Null]&#39;   : &#39;null&#39;, 
    &#39;[object Object]&#39;  : &#39;object&#39;
  };
  if(obj instanceof Element) {
    return &#39;element&#39;;
  }
  return map[toString.call(obj)];
}

Passez d'abord JSON.stringify, puis JSON.parse pour obtenir une copie approfondie. Mais le type de données ne prend en charge que les types numériques de base.

var obj = {
  a: &#39;a&#39;, 
  b: function(){console.log(&#39;b&#39;)}
}
 
//在JSON.stringify的时候就会把function给过滤了。
 
JSON.stringify(obj)// "{"a":"a"}"

Résumé

Voici un résumé de la copie profonde et comment mettre en œuvre une copie approfondie. Dans différents scénarios, il est nécessaire de déterminer si la copie approfondie doit être utilisée en fonction du scénario commercial.

Pour des articles plus détaillés sur la copie profonde javascript (deepClone), veuillez faire attention au site Web PHP chinois !

Déclaration:
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