L'objet JavaScript brut {key: 'value'}
peut être utilisé pour enregistrer des données structurées.
Mais une chose que je trouve très énervante : les clés des objets doivent être des chaînes (ou des symboles rarement utilisés).
Que se passerait-il si les chiffres étaient utilisés comme clés ? Il n'y a pas d'erreur dans ce cas :
const names = { 1: 'One', 2: 'Two', }; Object.keys(names); // => ['1', '2']
JavaScript convertit simplement implicitement les clés de l'objet en chaînes. C'est une chose délicate car vous perdez la cohérence du type.
Dans cet article, j'expliquerai comment l'objet JavaScript Map disponible dans ES2015 résout de nombreux problèmes des objets ordinaires, y compris la conversion des clés en chaînes.
Comme mentionné ci-dessus, si la clé de l'objet n'est pas une chaîne ou un symbole, JavaScript la convertira implicitement en chaîne.
Heureusement, map n'a aucun problème avec les types de clés :
const numbersMap = new Map(); numbersMap.set(1, 'one'); numbersMap.set(2, 'two'); [...numbersMap.keys()]; // => [1, 2]
1
et 2
sont des clés dans numbersMap
. Le type de ces clés numéro reste inchangé.
Vous pouvez utiliser n'importe quel type de clé dans une carte : nombres, booléens et chaînes et symboles classiques.
const booleansMap = new Map(); booleansMap.set(true, "Yep"); booleansMap.set(false, "Nope"); [...booleansMap.keys()]; // => [true, false]
booleansMap
Il n'y a aucun problème à utiliser des valeurs booléennes comme clés.
De même, les touches booléennes ne fonctionnent pas dans les objets normaux.
Repoussons les limites : peut-on utiliser un objet entier comme clé dans une carte ? bien sûr!
Supposons que vous deviez stocker certaines données liées à l'objet, mais ne attachez pas les données à l'objet lui-même.
Impossible de faire cela avec des objets normaux.
Une solution consiste à utiliser un tuple de valeurs d'objet :
const foo = { name: 'foo' }; const bar = { name: 'bar' }; const kindOfMap = [ [foo, 'Foo related data'], [bar, 'Bar related data'], ];
kindOfMap
est un tableau contenant une paire d'objets et des valeurs associées.
Le plus gros problème de cette approche est que la complexité temporelle de l'accès à la valeur par clé est O(n) . Vous devez parcourir l'ensemble du tableau pour obtenir la valeur souhaitée par clé :
function getByKey(kindOfMap, key) { for (const [k, v] of kindOfMap) { if (key === k) { return v; } } return undefined; } getByKey(kindOfMap, foo); // => 'Foo related data'
Avec WeakMap (une version spécialisée de Map
), vous n'avez pas besoin de vous en préoccuper. Il accepte les objets comme clés. La principale différence entre
Map
et WeakMap
est que ce dernier permet le garbage collection de l'objet qui est la clé, évitant ainsi les fuites de mémoire.
Le coût de refactorisation du code ci-dessus pour utiliser WeakMap
est trivial :
const foo = { name: 'foo' }; const bar = { name: 'bar' }; const mapOfObjects = new WeakMap(); mapOfObjects.set(foo, 'Foo related data'); mapOfObjects.set(bar, 'Bar related data'); mapOfObjects.get(foo); // => 'Foo related data'
Contrairement à Map
, WeakMap
n'accepte que les objets comme clés et a Simplifié ensemble de méthodes.
Tout objet en JavaScript hérite des propriétés de son objet prototype. Il en va de même pour les objets JavaScript classiques.
Si vous remplacez les propriétés héritées du prototype, vous pouvez casser le code qui dépend de ces propriétés du prototype :
function isPlainObject(value) { return value.toString() === '[object Object]'; } const actor = { name: 'Harrison Ford', toString: 'Actor: Harrison Ford' }; // Does not work! isPlainObject(actor); // TypeError: value.toString is not a function
Propriétés actor
définies sur l'objet toString
remplace l'héritage du prototype. toString()
méthode. Parce qu'il repose sur la méthode toString()
, cela casse isObject()
.
Consultez la liste des propriétés et méthodes dont les objets ordinaires héritent du prototype. Évitez d'utiliser ces noms pour définir des propriétés personnalisées.
Par exemple, imaginez que vous disposez d'une interface utilisateur qui gère certains champs personnalisés. Les utilisateurs peuvent ajouter des champs en spécifiant un nom et une valeur :
Il serait pratique de stocker l'état du champ personnalisé dans un objet normal :
const userCustomFields = { 'color': 'blue', 'size': 'medium', 'toString': 'A blue box' };
Mais l'utilisateur peut choisir un nom de champ personnalisé tel que toString
(comme indiqué dans l'exemple), constructor
etc., ce qui peut casser votre objet.
Ne créez pas de clés sur des objets normaux en acceptant les entrées de l'utilisateur !
la carte n'a pas ce problème. Le nom de la clé est illimité :
function isMap(value) { return value.toString() === '[object Map]'; } const actorMap = new Map(); actorMap.set('name', 'Harrison Ford'); actorMap.set('toString', 'Actor: Harrison Ford'); // Works! isMap(actorMap); // => true
La méthode actorMap
fonctionne indépendamment du fait que toString
possède ou non une propriété nommée toString()
.
Afin de parcourir les propriétés d'un objet normal, vous devez utiliser d'autres fonctions statiques auxiliaires, telles que Object.keys()
ou Object.entries()
(disponibles dans ES2017). ):
const colorsHex = { 'white': '#FFFFFF', 'black': '#000000' }; for (const [color, hex] of Object.entries(colorsHex)) { console.log(color, hex); } // 'white' '#FFFFFF' // 'black' '#000000'
Object.entries(colorsHex)
Renvoie un tableau de paires clé-valeur extraites de l'objet.
Cependant, la carte elle-même est itérable :
const colorsHexMap = new Map(); colorsHexMap.set('white', '#FFFFFF'); colorsHexMap.set('black', '#000000'); for (const [color, hex] of colorsHexMap) { console.log(color, hex); } // 'white' '#FFFFFF' // 'black' '#000000'
colorsHexMap
est itérable. Vous pouvez l'utiliser n'importe où itérable : for()
boucles, opérateur de propagation [...map]
etc.
map fournit également d'autres méthodes pour renvoyer des itérations : map.keys()
pour les clés et map.values()
pour les valeurs.
普通对象的另一个问题是你无法轻松确定其拥有的属性数量:
const exams = { 'John Smith': '10 points', 'Jane Doe': '8 points', }; Object.keys(exams).length; // => 2
要确定 exams
的大小,你必须通过它所有键来确定它们的数量。
map 提供了一种替代方法,通过它的访问器属性 size
计算键值对:
const examsMap = new Map([ ['John Smith', '10 points'], ['Jane Doe', '8 points'], ]); examsMap.size; // => 2
确定 map 的大小更加简单:examsMap.size
。
普通的 JavaScript 对象通常可以很好地保存结构化数据。但是它们有一些限制:
toString
,constructor
等)。所有这些问题都可以通过 map 轻松解决。而且它们提供了诸如迭代器和易于进行大小查找之类的好处。
不要将 map 视为普通对象的替代品,而应视为补充。
你知道 map 相对于普通对象的其他好处吗?请在下面写下你的评论!
原文地址:https://dmitripavlutin.com/maps-vs-plain-objects-javascript/
译文地址:https://segmentfault.com/a/1190000020660481
更多编程相关知识,请访问:编程课程!!
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!