diff --git a/1-js/05-data-types/07-map-set/article.md b/1-js/05-data-types/07-map-set/article.md index 5aa541ea..044d6392 100644 --- a/1-js/05-data-types/07-map-set/article.md +++ b/1-js/05-data-types/07-map-set/article.md @@ -12,7 +12,7 @@ But that's not enough for real life. That's why `Map` and `Set` also exist. [Map](mdn:js/Map) is a collection of keyed data items, just like an `Object`. But the main difference is that `Map` allows keys of any type. -The main methods are: +Methods and properties are: - `new Map()` -- creates the map. - `map.set(key, value)` -- stores the value by the key. @@ -57,7 +57,7 @@ visitsCountMap.set(john, 123); 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. +Using objects as keys is one of most notable and important `Map` features. For string keys, `Object` can be fine, but not for object keys. Let's try: @@ -94,7 +94,7 @@ map.set('1', 'str1') ## Map from Object -When a `Map` is created, we can pass an array (or another iterable) with key-value pairs, like this: +When a `Map` is created, we can pass an array (or another iterable) with key-value pairs for initialization, like this: ```js // array of [key, value] pairs @@ -105,7 +105,7 @@ let map = new Map([ ]); ``` -There is a built-in method [Object.entries(obj)](mdn:js/Object/entries) that returns an array of key/value pairs for an object exactly in that format. +If we have a plain object, and we'd like to create a `Map` from it, then we can use built-in method [Object.entries(obj)](mdn:js/Object/entries) that returns an array of key/value pairs for an object exactly in that format. So we can initialize a map from an object like this: @@ -168,10 +168,9 @@ recipeMap.forEach( (value, key, map) => { }); ``` - ## Set -A `Set` is a collection of values (without keys), where each value may occur only once. +A `Set` is a special type collection - "set of values" (without keys), where each value may occur only once. Its main methods are: @@ -182,6 +181,8 @@ Its main methods are: - `set.clear()` -- removes everything from the set. - `set.size` -- is the elements count. +The main feature is that repeated calls of `set.add(value)` with the same value don't do anything. That's the reason why each value appears in a `Set` only once. + For example, we have visitors coming, and we'd like to remember everyone. But repeated visits should not lead to duplicates. A visitor must be "counted" only once. `Set` is just the right thing for that: @@ -239,13 +240,30 @@ The same methods `Map` has for iterators are also supported: `Map` -- is a collection of keyed values. +Methods and properties: + +- `new Map([iterable])` -- creates the map, with optional `iterable` (e.g. array) of `[key,value]` pairs for initialization. +- `map.set(key, value)` -- stores the value by the key. +- `map.get(key)` -- returns the value by the key, `undefined` if `key` doesn't exist in map. +- `map.has(key)` -- returns `true` if the `key` exists, `false` otherwise. +- `map.delete(key)` -- removes the value by the key. +- `map.clear()` -- removes everything from the map. +- `map.size` -- returns the current element count. + The differences from a regular `Object`: - Any keys, objects can be keys. -- Iterates in the insertion order. - Additional convenient methods, the `size` property. `Set` -- is a collection of unique values. -- Keeps the insertion order. -- Doesn't allow to reorder elements. +Methods and properties: + +- `new Set([iterable])` -- creates the set, with optional `iterable` (e.g. array) of values for initialization. +- `set.add(value)` -- adds a value (does nothing if `value` exists), returns the set itself. +- `set.delete(value)` -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. +- `set.has(value)` -- returns `true` if the value exists in the set, otherwise `false`. +- `set.clear()` -- removes everything from the set. +- `set.size` -- is the elements count. + +Iteration over `Map` and `Set` is always in the insertion order, so we can't say that these collections are unordered, but we can't reorder elements or directly get an element by its number. diff --git a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md index cae82625..f0c6ed45 100644 --- a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md +++ b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md @@ -40,4 +40,4 @@ messages[0][isRead] = true; Now third-party code probably won't see our extra property. -Both solutions are possible, though the one with `WeakSet` is "cleaner" from the architectural point of view. +Although symbols allow to lower the probability of problems, using `WeakSet` is better from the architectural point of view. diff --git a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md index c9ec862c..c3d3bbc0 100644 --- a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md +++ b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/task.md @@ -20,4 +20,4 @@ Now, which data structure you could use to store information whether the message P.S. When a message is removed from `messages`, it should disappear from your structure as well. -P.P.S. We shouldn't modify message objects directly. As they are managed by someone else's code, adding extra properties to them may have bad consequences. +P.P.S. We shouldn't modify message objects, add our properties to them. As they are managed by someone else's code, that may lead to bad consequences. diff --git a/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/task.md b/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/task.md index 17df4976..8e341c18 100644 --- a/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/task.md +++ b/1-js/05-data-types/08-weakmap-weakset/02-recipients-when-read/task.md @@ -17,3 +17,5 @@ let messages = [ The question now is: which data structure you'd suggest to store the information: "when the message was read?". In the previous task we only needed to store the "yes/no" fact. Now we need to store the date, and it should only remain in memory until the message is garbage collected. + +P.S. Dates can be stored as objects of built-in `Date` class, that we'll cover later.