fixes
This commit is contained in:
parent
f6e2c899c2
commit
5498450646
4 changed files with 124 additions and 22 deletions
|
@ -58,7 +58,24 @@ alert( visitsCountMap.get(john) ); // 123
|
|||
|
||||
Using objects as keys is one of most notable and important `Map` features. For string keys, `Object` can be fine, but it would be difficult to replace the `Map` with a regular `Object` in the example above.
|
||||
|
||||
In the old times, before `Map` existed, people added unique identifiers to objects for that:
|
||||
Let's try:
|
||||
|
||||
```js run
|
||||
let john = { name: "John" };
|
||||
|
||||
let visitsCountObj = {}; // try to use an object
|
||||
|
||||
visitsCountObj[john] = 123; // try to use john object as the key
|
||||
|
||||
*!*
|
||||
// That's what got written!
|
||||
alert( visitsCountObj["[object Object]"] ); // 123
|
||||
*/!*
|
||||
```
|
||||
|
||||
As `john` is an object, it got converted to the key string `"[object Object]"`. All objects without a special conversion handling are converted to such string, so they'll all mess up.
|
||||
|
||||
In the old times, before `Map` existed, people used to add unique identifiers to objects for that:
|
||||
|
||||
```js run
|
||||
// we add the id field
|
||||
|
@ -159,7 +176,7 @@ The iteration goes in the same order as the values were inserted. `Map` preserve
|
|||
Besides that, `Map` has a built-in `forEach` method, similar to `Array`:
|
||||
|
||||
```js
|
||||
// runs the function for each (key, value) pair
|
||||
// runs the function for each (key, value) pair
|
||||
recipeMap.forEach( (value, key, map) => {
|
||||
alert(`${key}: ${value}`); // cucumber: 500 etc
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
# Object.keys, values, entries
|
||||
|
||||
Let's step away from the individual data structures and talk about the iterations over them.
|
||||
Let's step away from the individual data structures and talk about the iterations over them.
|
||||
|
||||
In the previous chapter we saw methods `map.keys()`, `map.values()`, `map.entries()`.
|
||||
|
||||
These methods are generic, there is a common agreement to use them for data structures. If we ever create a data structure of our own, we should implement them too.
|
||||
These methods are generic, there is a common agreement to use them for data structures. If we ever create a data structure of our own, we should implement them too.
|
||||
|
||||
They are supported for:
|
||||
|
||||
|
@ -63,8 +63,93 @@ for (let value of Object.values(user)) {
|
|||
}
|
||||
```
|
||||
|
||||
## Object.keys/values/entries ignore symbolic properties
|
||||
|
||||
```warn header="Object.keys/values/entries ignore symbolic properties"
|
||||
Just like a `for..in` loop, these methods ignore properties that use `Symbol(...)` as keys.
|
||||
|
||||
Usually that's convenient. But if we want symbolic keys too, then there's a separate method [Object.getOwnPropertySymbols](mdn:js/Object/getOwnPropertySymbols) that returns an array of only symbolic keys. Also, the method [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) returns *all* keys.
|
||||
Usually that's convenient. But if we want symbolic keys too, then there's a separate method [Object.getOwnPropertySymbols](mdn:js/Object/getOwnPropertySymbols) that returns an array of only symbolic keys. Also, there exist a method [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) that returns *all* keys.
|
||||
```
|
||||
|
||||
## Object.fromEntries to transform objects
|
||||
|
||||
Sometimes we need to perform a transformation of an object to `Map` and back.
|
||||
|
||||
We already have `new Map(Object.entries(obj))` to make a `Map` from `obj`.
|
||||
|
||||
The syntax of `Object.fromEntries` does the reverse. Given an array of `[key, value]` pairs, it creates an object:
|
||||
|
||||
```js run
|
||||
let prices = Object.fromEntries([
|
||||
['banana', 1],
|
||||
['orange', 2],
|
||||
['meat', 4]
|
||||
]);
|
||||
|
||||
// now prices = { banana: 1, orange: 2, meat: 4 }
|
||||
|
||||
alert(prices.orange); // 2
|
||||
```
|
||||
|
||||
Let's see practical applications.
|
||||
|
||||
For example, we'd like to create a new object with double prices from the existing one.
|
||||
|
||||
For arrays, we have `.map` method that allows to transform an array, but nothing like that for objects.
|
||||
|
||||
So we can use a loop:
|
||||
|
||||
```js run
|
||||
let prices = {
|
||||
banana: 1,
|
||||
orange: 2,
|
||||
meat: 4,
|
||||
};
|
||||
|
||||
let doublePrices = {};
|
||||
for(let [product, price] of Object.entries(prices)) {
|
||||
doublePrices[product] = price * 2;
|
||||
}
|
||||
|
||||
alert(doublePrices.meat); // 8
|
||||
```
|
||||
|
||||
...Or we can represent the object as an `Array` using `Object.entries`, then perform the operations with `map` (and potentially other array methods), and then go back using `Object.fromEntries`.
|
||||
|
||||
Let's do it for our object:
|
||||
|
||||
```js run
|
||||
let prices = {
|
||||
banana: 1,
|
||||
orange: 2,
|
||||
meat: 4,
|
||||
};
|
||||
|
||||
*!*
|
||||
let doublePrices = Object.fromEntries(
|
||||
// convert to array, map, and then fromEntries gives back the object
|
||||
Object.entries(prices).map(([key, value]) => [key, value * 2])
|
||||
);
|
||||
*/!*
|
||||
|
||||
alert(doublePrices.meat); // 8
|
||||
```
|
||||
|
||||
It may look difficult from the first sight, but becomes easy to understand after you use it once or twice.
|
||||
|
||||
We also can use `fromEntries` to get an object from `Map`.
|
||||
|
||||
E.g. we have a `Map` of prices, but we need to pass it to a 3rd-party code that expects an object.
|
||||
|
||||
Here we go:
|
||||
|
||||
```js run
|
||||
let map = new Map();
|
||||
map.set('banana', 1);
|
||||
map.set('orange', 2);
|
||||
map.set('meat', 4);
|
||||
|
||||
let obj = Object.fromEntries(map);
|
||||
|
||||
// now obj = { banana: 1, orange: 2, meat: 4 }
|
||||
|
||||
alert(obj.orange); // 2
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue