Maison  >  Article  >  interface Web  >  Explication détaillée du transfert et de la copie js

Explication détaillée du transfert et de la copie js

小云云
小云云original
2018-03-13 16:12:281326parcourir

Nous savons que js a plusieurs types de données de base et d'autres types de données complexes, notamment (objets, tableaux, fonctions). L'affectation des types de données de base est en fait une copie de la valeur, et nous l'appelons le transfert de valeur, et la variable après. affectation Il n'y a pas d'autre relation avec la variable d'origine sauf que la valeur est égale.

let x = 666
let y = x
let m = 'abc'
let n = m
y = 888
n = 'def'
console.log(x, y)//666,888
console.log(m, n)//'abc','def'

Le transfert de types de données complexes n'est pas comme ça, car lorsqu'une variable est liée à un type de données complexe, ce qui est enregistré n'est pas la valeur des données complexes, mais le stockage des données . Une information d'adresse, lors de l'affectation de cette variable à une autre variable, seule l'adresse est transmise. Les deux variables pointent en fait vers une information de données. Lorsqu'une variable est modifiée, les autres variables seront affectées. Cette méthode de transfert est appelée passage. référence

let obj1 = {
    a : '1',
    b : 2
} 
let obj2 = obj1
obj2.b = 3
console.log(obj1,obj2)//{a: "1", b: 3},{a: "1", b: 3}

copie

Nous savons que l'affectation de types de données complexes est transmise par référence et que les variables avant et après l'affectation s'influencent souvent dans les projets réels. Nous ne voulons pas cela, par exemple :

Nous utilisons des données (un tableau) à deux endroits dans une vue. L'un est qu'une liste n'a besoin que d'afficher les données dans l'ordre, et l'autre est qu'un. chart nécessite Après avoir inversé les données puis effectué le traitement des données, nous aurons un problème si la première liste après data.reverse() est également dans l'ordre inverse, ce n'est pas ce que nous voulons. Nous avons besoin d'une méthode pour copier uniquement la valeur. du tableau.Et l'adresse des données de ce nouveau tableau est différente de celle du tableau d'origine. Cette méthode de copie est appelée copie de tableau.

let obj1 = {a:1, b:{c:2}}
let shallowCopy = (src)=> {
    let dst = {}
    for (let prop in src) {
        if (src.hasOwnProperty(prop)) {
          dst[prop] = src[prop]
        }
    }
    return dst
}
let obj2 = shallowCopy(obj1)
console.log(obj1,obj2) //@1
obj1.a = 6
console.log(obj2.a) //@2
obj2.b.c = 666
console.log(obj1.b.c) //@3
obj2.b = {
    c: 888
}
console.log(obj1.b.c) //@4

On peut voir dans l'exemple ci-dessus que l'attribut de première couche d'obj1 copie la valeur de l'attribut et n'hérite pas de la copie de l'adresse, mais la deuxième couche est que l'attribut b partage un adresse mémoire, qui est une copie superficielle. , mais à @4, obj1 n'a pas été affecté par obj2, car l'attribut b est un objet. Pour ce type de réaffectation par référence, l'ordinateur réaffectera une nouvelle mémoire pour stocker les données et enregistrer. informations d'adresse, donc à l'heure actuelle, obj1.b.c et obj2.b.c ne sont plus une valeur d'attribut de l'enregistrement

peut également être comprise comme : la copie est destinée au transfert. L'affectation directe de types de données complexes est un transfert par référence. et ne peut pas être appelé copie. La copie est une simple sauvegarde des données originales. Les informations d'adresse mémoire des données ne sont pas exactement les mêmes. En effet, la copie est également divisée en copie superficielle et copie approfondie.

Une copie non imbriquée d'un type de données complexe signifie que seule la première couche d'informations sur les données est copiée, ce qui est une copie superficielle. Si la première couche de données a un type de données complexe, elle est quand même transmise. par référence. , ce qui est copié sont toujours les informations d'adresse, et la copie imbriquée multicouche des objets de tableau, etc. implémentée par d'autres méthodes est une copie complète.

Voyons comment les tableaux et les objets implémentent des copies profondes et superficielles :

Copie de tableaux

  • méthode slice

    let arr1 = [1,2,[3,4]]
    let arr2 = arr1.slice(0)
    arr2[2].push(5)
    arr2.push(6)
    console.log(arr1,arr2)
  • méthode de concat

    let arr1 = [1,2,[3,4]]
    let arr2 = arr1.concat()
    arr2[2].push(5)
    arr2.push(6)
    console.log(arr1,arr2)
  • for boucle

    let arr1 = [1,2,[3,4]]
    let arr2 = []
    for(let i = 0; i<arr1.length; i++){
        arr2.push(arr1[i])
    }
    arr2[2].push(5)
    arr2.push(6)
    console.log(arr1,arr2)
  • …opérateur

    let arr1 = [1,2,[3,4]]
    let [...arr2] = arr1
    arr2[2].push(5)
    arr2.push(6)
    console.log(arr1,arr2)

Les copies des quatre types de tableaux ci-dessus sont toutes des copies superficielles. Pour réaliser la copie profonde du tableau, elle doit être implémentée de manière récursive

let deepClone = (src)=> {
    let result
    (src instanceof Array) ? (result = []) :(result = {})
    for (let key in src) {
        result[key] = (typeof src[key] === &#39;object&#39;) ? deepClone(src[key]) : src[key]//数组和对象的type都是object
    }
    return result
}   
let arr1 = [1,2,[3,4]]
let arr2 = deepClone(arr1)
arr2[2].push(5)
arr2.push(6)
console.log(arr1,arr2)

Vous pouvez trouver. la méthode arr1[2] Contrairement à arr2[2], la même méthode de copie profonde ci-dessus est également applicable à la copie de l'objet

objet

  • boucle for universelle

    let obj1 = {a:1,b:{c:2}}
    let obj2 = {}
    for(let key in obj1){
        obj2[key] = obj1[key]
    }
    obj1.b.c = 6
    console.log(obj1,obj2)
  • …Opérateur

    let obj1 = {a:1,b:{c:2}}
    let {...obj2} = obj1
    obj1.b.c = 6
    console.log(obj1,obj2)
  • Object.assign()

    let obj1 = {a:1,b:{c:2}}
    let obj2 = Object.assign({},obj1)
    obj1.b.c = 6
    console.log(obj1,obj2)

Les 3 types ci-dessus La méthode est une copie superficielle de l'objet. Voici deux méthodes de copie profonde de l'objet :

  • convertir en chaîne puis revenir en objet

    let obj1 = {a:1,b:{c:2}}
    let obj2 = JSON.parse(JSON.stringify(obj1))
    obj1.b.c = 6
    console.log(obj1,obj2)
  • La méthode deepClone est la méthode deepClone du tableau ci-dessus

Concepts associés

Fonction pure

Donné une entrée dans une fonction, elle renvoie une fonction unique. Une fonction qui a une sortie et n'a aucun impact sur l'environnement externe est appelée une fonction pure. Les variables définies à l'intérieur seront recyclées par le mécanisme de récupération de place après le retour de la fonction.

Mais si le paramètre de la fonction est un tableau, un objet ou une fonction, une référence est transmise et l'opération affectera les données d'origine. La fonction écrite de cette manière aura des effets accessoires et la rendra lisible. La sexualité devient faible.

Le moyen de réduire l'impact est de faire une copie complète des paramètres entrants et de les affecter à une nouvelle variable pour éviter que les paramètres d'origine ne soient falsifiés.

Regardons un exemple de fonction pure :

let pureFunc = (animal)=> {
    let newAnimal = JSON.parse(JSON.stringify(animal))
    newAnimal.type = &#39;cat&#39;
    newAnimal.name = &#39;Miao&#39;
    return newAnimal
}

let wang = {
    type: &#39;dog&#39;,
    name: &#39;Wang&#39;
}

let miao = pureFunc(wang)
console.log(wang,miao)
A travers l'exemple ci-dessus, vous pouvez voir que wang n'a pas été modifié par une fonction pure.

Repensons à l'exemple suivant. Si vous y répondez correctement, cela signifie que vous avez une compréhension approfondie de ce dont parle cet article (rappelez-le à tout le monde—>réaffectation des références)

let afterChange = (obj)=>{
    obj.a = 6
    obj = {
        a: 8,
        b: 9
    }
    return obj
}
let objIns = {
    a: 1,
    b: 2
}

let objIns2 = afterChange(objIns)
console.log(objIns, objIns2)
Ce qui précède est ma compréhension de la référence et de la transmission de js. Veuillez me pardonner s'il y a un caractère inapproprié. Merci !

Vous pouvez également lire d'autres articles pour approfondir votre compréhension. Je recommande cette valeur explicative par rapport à la référence en Javascript.

Recommandations associées :


Fonction JS passant des paramètres par valeur

Tutoriel d'illustration de passage de paramètres JavaScript

Une brève analyse de la transmission json en php et js

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en 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