1 votes

Utiliser et comprendre JavaScript Maps

Le document MDN sur le Objet Map JavaScript fournit des informations utiles mais semble omettre quelques points importants. Ils sont peut-être évidents pour la plupart des gens, mais je ne comprends pas pourquoi cela fonctionne de cette façon et j'apprécierais une clarification.

Il apparaît que les clés, lorsqu'elles ne sont pas des chaînes de caractères, sont des références à des objets, y compris des objets fonctionnels. Et, en dehors des objets fonctions, il apparaît que les valeurs des objets sont des références aux objets également. Ainsi, dans le code ci-dessous, mapF.get(updateFunc).b = 25 met à jour l'objet contenu dans la carte, par opposition à l'objet mapF.get() renvoyant uniquement une copie de l'objet.

Mais cela ne semble pas être le cas lorsque la valeur est un objet fonction, mais semble faire une copie de la fonction, de sorte qu'après la fonction funcInMap est mis à jour, le mapF.get('funcInMap')(4) renvoie à 8 au lieu de 12 ; et semble donc détenir une copie de la définition originale de la funcInMap .

Est-ce que je fais une erreur ou est-ce que c'est ainsi que cela fonctionne et que l'on doit s'attendre à ce que cela fonctionne ? Merci.

var funcInMap = function (x) {
 return x * 2;
};
function updateFunc() {
  funcInMap = function (x) { return x * 3; };
}
var mapF = new Map();

mapF.set(updateFunc, {a: 5, b: 10});
mapF.set('funcInMap',funcInMap);

console.log("b pre map update: " + mapF.get(updateFunc).b); // 10
mapF.get(updateFunc).b = 25;
console.log("b post map update: " + mapF.get(updateFunc).b); // 25
console.log(mapF.get(updateFunc));
console.log("funcInMap pre update : " + mapF.get('funcInMap')(4)); // 8

updateFunc();
console.log("funcInMap post update : " + funcInMap(4)); // 12

console.log("mapF funcInMap post update : " + mapF.get('funcInMap')(4)); // 8

Ajouté après avoir reçu la réponse.

function updateFunc() { }

var mapF = new Map(),
    obj = {a: 5, b: 10};
mapF.set(updateFunc, obj);

console.log("Original obj: " + Object.values(mapF.get(updateFunc))); 
// Return 5, 10

obj = {a: 105, b: 110};

console.log("Updated obj: " + Object.values(mapF.get(updateFunc))); 
// Return 5, 10

/*
  I would've been stupid to expect the second group to return
  105, 110; but that is what I was expecting when the objects
  were functions.
*/

Après avoir modifié une partie du code de mon projet afin d'utiliser des cartes au lieu d'objets ordinaires, je me suis rendu compte que j'étais à nouveau un peu stupide en définissant un fichier de type map key d'avoir un value qui est un object . Cela aurait peut-être du sens dans certains cas ; mais si l'objectif est de relier certaines données à un élément ou à une fonction DOM d'une manière similaire à l'ajout de propriétés à ces derniers, mais qui ne s'entrechoqueront jamais à l'avenir, ne serait-il pas préférable d'ajouter une balise map à un map ?

Ainsi, l'exemple de code ci-dessus de mapF.set(updateFunc, {a: 5, b: 10}) devrait être mapF.set(updateFunc, new Map( [ ['a', 5], ['b', 10] ] ) ) et les propriétés peuvent être ajoutées (etc.) à l'aide de la fonction mapF.get(updateFunc).set('c', 20) .

Cependant, l'intérieur map ne peut être utilisé sans utilisation get deux fois. Ainsi, il semblerait qu'un null object serait de toute façon plus facile à coder.

function myFunc() { };

var map_map = new Map([ [myFunc, new Map([ ['a',10], ['b',20]]) ] ] );

var obj = Object.create(null, {
 a: { value: 10, enumerable: true },
 b: { value: 20, enumerable: true }
});

var map_obj = new Map([[myFunc, obj]]);

console.log( map_map.get(myFunc).get('a') ); //=> 10
console.log( map_map.get(myFunc)['a'] ); //=> undefined
console.log( map_obj.get(myFunc).a); // => 10

2voto

Mister Jojo Points 11938

Lorsque vous écrivez en JS :

var funcInMap = function (x) { return x * 2; };

l'interpréteur JS crée 2 choses :

-1- le code assembleur correspondant à function (x) { return x * 2; }
qu'il place à une adresse mémoire @_memoryAddress_x1

-2- créer le funcInMap à laquelle il attache l'adresse mémoire @_memoryAddress_x1

par la suite, vous avez codé :

mapF.set('funcInMap',funcInMap);

que l'interpréteur JS "transforme" en
mapF.set('funcInMap', @_memoryAddress_x1);
parce que @_memoryAddress_x1 correspond au contenu de l'élément funcInMap variable

sur updateFunc() vous faites une opération similaire : il crée un code d'assemblage pour
function (x) { return x * 3; }
à une adresse = @_memoryAddress_ZZ

et remplacer la valeur de funcInMap con @_memoryAddress_ZZ

mais l'adresse @_memoryAddress_x1 existe toujours
ainsi que son code d'assemblage pour l'exécution.

Dans une logique similaire (pas besoin d'utiliser les Map Objects)

let
  function_A = () => 'a'
, function_B = () => 'b'
, function_C = function_A
  ;

console.log( function_A() )   // return 'a'
console.log( function_C() )   // return 'a'

function_A = function_B

console.log( function_A() )   // return 'b'
console.log( function_C() )   // return 'a'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X