Maison > interface Web > js tutoriel > le corps du texte

Parlez des problèmes causés par l'utilisation d'opérations d'affectation consécutives dans les compétences javascript_javascript

WBOY
Libérer: 2016-05-16 15:29:36
original
1140 Les gens l'ont consulté

Avant-propos

Cette phrase dans le titre de l'article a été initialement vue dans une spécification JavaScript étrangère, à cette époque, elle n'a pas suffisamment attiré l'attention jusqu'à ce qu'un bug ait récemment découvert les caractéristiques (pièges) de l'opération d'affectation continue dans JS.

Après une recherche en ligne, j'ai trouvé un très bon exemple de mission continue (source 1, source 2) :

var a = {n:1};
a.x = a = {n:2};
console.log(a.x); // 输出?
Copier après la connexion

La réponse est :

console.log(a.x); // undefined
Copier après la connexion

Je ne sais pas si vous avez la bonne réponse, du moins je me suis trompée.

J'en ai donc profité pour regarder de plus près le fonctionnement de l'affectation continue JS

Ordre de mission ?

Supposons qu'il y ait un code : A=B=C; , l'ordre d'exécution des instructions d'affectation est de droite à gauche, donc le problème est :

La conjecture 1 est-elle : B = C ;

Ou devinez 2 : B = C ; A = B ?

Nous savons tous que si deux objets pointent vers un objet en même temps, alors la modification de cet objet est synchronisée, comme par exemple :

var a={n:1};
var b=a;
a.n=2;
console.log(b);//Object {n: 2}
Copier après la connexion

Vous pouvez ainsi tester l'ordre des devoirs consécutifs en fonction de cette fonctionnalité.

Selon la conjecture 1, remplacez C par un objet spécifique. Vous pouvez voir que la modification de a ne sera pas synchronisée avec b, car deux {n:1} sont créés lors de l'exécution de la première et de la deuxième lignes de l'objet. Tel que :

var b={n:1};
var a={n:1};
a.n=0;
console.log(b);//Object {n: 1}
Copier après la connexion

Selon la conjecture 2, remplacez C par un objet spécifique. Vous pouvez voir que la modification de a est synchronisée avec b, car a et b font référence à un objet en même temps, comme :

var b={n:1};
var a=b;
a.n=0;
console.log(b);//Object {n: 0}
Copier après la connexion

Test d'une véritable affectation continue :

var a,b;
a=b={n:1};
a.n=0;
console.log(b);//Object {n: 0}
Copier après la connexion

Vous pouvez voir qu'il est cohérent avec la conjecture 2. Si quelqu'un estime que ce test est inexact, vous pouvez le tester à nouveau et utiliser les fonctionnalités setter et getter d'ECMA5 pour tester.

Tout d'abord, les setters et les getters sont appliqués aux noms de variables, et non aux objets réellement stockés dans les variables, comme suit :

Object.defineProperty(window,"obj",{
 get:function(){
  console.log("getter!!!");
 }
});
var x=obj;
obj;//getter!!! undefined
x;//undefined
Copier après la connexion

Vous pouvez voir que seul obj génère "getter !!!", mais pas x. Utilisez cette fonctionnalité pour tester.

Test d'affectation continue 2 :

Object.defineProperty(window,"obj",{
 get:function(){
  console.log("getter!!!");
 }
});
a=b=obj;//getter!!! undefined
Copier après la connexion

Confirmé à nouveau via getter, dans A=B=C, C n'est lu qu'une seule fois.

Ainsi, la véritable règle de fonctionnement de l'affectation continue est B = C = A = B ; c'est-à-dire que l'affectation continue prend toujours uniquement le résultat de l'expression du côté droit du signe égal de droite à gauche ; côté du signe égal.

Le devoir continu peut-il être rédigé séparément ?

Vous pouvez voir les vraies règles de l'affectation continue à partir de ce qui précède. Revenez ensuite au cas au début de l'article. Si vous divisez l'affectation continue selon les règles ci-dessus, vous constaterez que le résultat est différent, tel. comme :

var a={n:1};
a={n:2};
a.x=a;
console.log(a.x);//Object {n: 2, x: Object}
Copier après la connexion

Ainsi, bien que l'instruction d'affectation continue suive les règles d'affectation de droite à gauche, elle ne peut toujours pas être écrite dans des instructions séparées. Quant au pourquoi

.

Je suppose : afin de garantir l'exactitude de l'instruction d'affectation, js supprimera d'abord une copie de toutes les adresses de référence à attribuer avant d'exécuter une instruction d'affectation, puis attribuera les valeurs une par une.

Je pense donc que la logique de ce code a.x=a={n:2} est :

;

1. Avant l'exécution, les adresses de référence de a dans a et a.x seront d'abord supprimées. Cette valeur pointe vers {n:1}

.

2. Créez un nouvel objet {n:2} en mémoire

3. Exécutez a={n:2} et changez la référence de a de pointant vers {n:1} vers pointant vers le nouveau {n:2}

4. Exécutez a.x=a. À ce moment, a pointe déjà vers le nouvel objet, et comme a.x conserve la référence d'origine avant l'exécution, a.x's a pointe toujours vers l'objet {n:1} d'origine, donc le un nouvel objet est donné à l'objet d'origine. Ajoutez un attribut x avec le contenu {n:2}, qui est maintenant un

.

5. L'exécution de l'instruction se termine, l'objet d'origine passe de {n:1} à {n:1,x:{n:2}}, et l'objet d'origine est recyclé par GC car plus personne ne le référence. Actuellement, pointer vers un nouvel objet {n:2}

6. Nous avons donc le résultat courant au début de l'article, puis exécutons a.x, il sera naturellement indéfini

Le processus ci-dessus est illustré par le numéro de série :

En suivant le processus ci-dessus, on peut voir que l'ancien a.x et le nouveau a pointent tous deux vers l'objet nouvellement créé {n:2}, ils devraient donc être congruents.

Test :

var a = {n:1};
var b = a;
a.x = a = {n:2};
console.log(a===b.x); //true
Copier après la connexion

Parce que nous avons ajouté var b=a, ce qui signifie ajouter une référence à l'objet d'origine, il ne sera pas publié à l'étape 5 ci-dessus, ce qui confirme la conclusion ci-dessus.

Post-scriptum

C'est à cette époque que j'ai découvert les caractéristiques de l'affectation continue. En repensant au titre de l'article, il semble qu'il devrait s'appeler :

.

Essayez de ne pas utiliser l'opération d'affectation continue de JS à moins de vraiment comprendre son mécanisme interne et ses conséquences possibles.

É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