console.log() affiche la valeur modifiée d'une variable avant que la valeur ne change réellement

Ce peu de code que je comprends. Nous faisons une copie de A et l'appelons C. Quand A est changé C reste le même

var A = 1;
var C = A;
console.log(C); // 1
A++;
console.log(C); // 1

Mais quand A est un tableau, nous avons une sitiuation différente. Non seulement C va changer, mais il change avant même que nous touchions a

var A = [2, 1];
var C = A;
console.log(C); // [1, 2]
A.sort();
console.log(C); // [1, 2]

Quelqu'un peut-il expliquer ce qui s'est passé dans le deuxième exemple?

30
demandé sur Elliot B. 2012-07-01 22:36:45

5 réponses

Pointu réponse a de bonnes informations, mais ce n'est pas la bonne réponse à cette question.

Le comportement décrit par L'OP fait partie d'un bug qui a été signalé pour la première fois en mars 2010, patché pour Webkit en août 2012, mais à ce jour n'est pas encore intégré dans Google Chrome. Le comportement dépend si la fenêtre de débogage de la console est ouverte oufermée au moment où le littéral de l'objet est passé à console.log().

Extraits de l'original rapport de bogue ( https://bugs.webkit.org/show_bug.cgi?id=35801):

Description de mitch kramer 2010-03-05 11: 37: 45 PST

1) Créez un littéral d'objet avec une ou plusieurs propriétés

2) de la console.enregistrez cet objet mais laissez-le FERMÉ (ne le développez pas dans la console)

3) variation de l'une des propriétés à une nouvelle valeur

Ouvrez maintenant cette console.connectez-vous et vous verrez qu'il a la nouvelle valeur pour une raison quelconque, même si sa valeur était différents au moment où il a été généré.

Je tiens à souligner que si vous l'ouvrez, il conservera la valeur correcte si ce n'était pas clair.

Réponse d'un développeur de Chrome:

Commentaire # 2 de Pavel Feldman 2010-03-09 06: 33: 36 PST

Je ne pense pas que nous allons jamais réparer celui-ci. Nous ne pouvons pas cloner l'objet en le déversant dans la console et nous ne pouvons pas non plus écouter les modifications des propriétés de l'objet afin de le rendre toujours actuel.

Nous devrions nous assurer que le comportement existant est attendu.

Beaucoup de plaintes ont suivi et finalement cela a conduit à une correction de bug.

Notes du Changelog du patch implémenté en août 2012 ( http://trac.webkit.org/changeset/125174):

À partir d'aujourd'hui, le dumping d'un objet (tableau) dans la console entraînera les propriétés des objets étant lire sur l'expansion de l'objet console (c'est-à-dire paresseusement). Cela signifie que le dumping du même objet tout en la mutation de il sera être difficile à déboguer en utilisant la console.

Cette modification commence à générer des aperçus abrégés pour les objets / tableaux au moment de leur journalisation et transmet ces informations dans le front-end. Cela ne se produit que lorsque le frontal est déjà ouvert, il ne fonctionne que pour la console.log (), pas l'interaction de la console en direct.

23
répondu Elliot B. 2018-04-12 17:58:31

Les tableaux

Sont des objets . Les Variables renvoient aux objets. Ainsi, une affectation dans le second cas copiait la référence dans le tableau de " A " à "C". Après cela, les deux variables se réfèrent au même objet unique (le tableau).

Les valeurs primitives comme les nombres sont complètement copiées d'une variable à l'autre dans des affectations simples comme la vôtre. L'instruction A++; attribue une nouvelle valeur à "A".

Pour le dire autrement: la valeur d'une variable peut être soit une valeur primitive (un nombre, un booléen, null ou une chaîne), soit il peut s'agir d'une référence à un objet. Le cas des primitives de chaîne est un peu bizarre, car elles ressemblent plus à des objets qu'à des valeurs primitives (scalaires), mais elles sont immuables, donc il est correct de prétendre qu'elles sont juste comme des nombres.

10
répondu Pointy 2012-07-01 18:38:09

EDIT: garder cette réponse juste pour préserver les commentaires utiles ci-dessous.

@Esailija a réellement raison - console.log() ne consignera pas nécessairement la valeur de la variable au moment où vous avez essayé de la consigner. Dans votre cas, les deux appels à console.log() enregistre la valeur de C après tri.

Si vous essayez d'exécuter le code en question dans 5 états distincts dans la console, vous verrez le résultat que vous attendiez (première, [2, 1], puis [1, 2]).

4
répondu Dmytro Shevchenko 2012-07-01 19:12:14

Console.log() enregistre l'objet d'où le changement dans l'impression. Pour éviter cela, procédez comme suit:

console.log(JSON.parse(JSON.stringify(c)))

Pour plus d'informations https://developer.mozilla.org/en-US/docs/Web/API/Console/log

4
répondu Ka Tech 2018-02-25 02:21:56

Bien que cela ne fonctionne pas dans toutes les situations, j'ai fini par utiliser un "point de rupture" pour résoudre ce problème:

mysterious = {property:'started'}

// prints the value set below later ?
console.log(mysterious)

// break,  console above prints the first value, as god intended
throw new Error()

// later
mysterious = {property:'changed', extended:'prop'}
3
répondu benipsen 2012-08-26 05:08:01