Maison >interface Web >js tutoriel >Explication détaillée du transfert et de la copie js
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}
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 :
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] === 'object') ? 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
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)
let pureFunc = (animal)=> { let newAnimal = JSON.parse(JSON.stringify(animal)) newAnimal.type = 'cat' newAnimal.name = 'Miao' return newAnimal } let wang = { type: 'dog', name: 'Wang' } 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!