Merge branch 'master' of https://github.com/javascript-tutorial/en.javascript.info into minor-fixes
This commit is contained in:
commit
dfb4f00ced
31 changed files with 1209 additions and 49 deletions
|
@ -4,7 +4,7 @@ importance: 5
|
|||
|
||||
# Check for spam
|
||||
|
||||
Write a function `checkSpam(str)` that returns `true` if `str` contains 'viagra' or 'XXX', otherwise false.
|
||||
Write a function `checkSpam(str)` that returns `true` if `str` contains 'viagra' or 'XXX', otherwise `false`.
|
||||
|
||||
The function must be case-insensitive:
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ The array in the process:
|
|||
|
||||
```js no-beautify
|
||||
Jazz, Blues
|
||||
Jazz, Bues, Rock-n-Roll
|
||||
Jazz, Blues, Rock-n-Roll
|
||||
Jazz, Classics, Rock-n-Roll
|
||||
Classics, Rock-n-Roll
|
||||
Rap, Reggae, Classics, Rock-n-Roll
|
||||
|
|
|
@ -453,7 +453,7 @@ We can use an array as a deque with the following operations:
|
|||
- `push(...items)` adds `items` to the end.
|
||||
- `pop()` removes the element from the end and returns it.
|
||||
- `shift()` removes the element from the beginning and returns it.
|
||||
- `unshift(...items)` adds items to the beginning.
|
||||
- `unshift(...items)` adds `items` to the beginning.
|
||||
|
||||
To loop over the elements of the array:
|
||||
- `for (let i=0; i<arr.length; i++)` -- works fastest, old-browser-compatible.
|
||||
|
|
|
@ -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
|
||||
});
|
||||
|
@ -172,7 +189,7 @@ A `Set` is a collection of values, where each value may occur only once.
|
|||
|
||||
Its main methods are:
|
||||
|
||||
- `new Set(iterable)` -- creates the set, optionally from an array of values (any iterable will do).
|
||||
- `new Set(iterable)` -- creates the set, and if an `iterable` object is provided (usually an array), copies values from it into the set.
|
||||
- `set.add(value)` -- adds a value, 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`.
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -37,7 +37,7 @@ The loop variant is also a little bit more complicated then the direct output.
|
|||
|
||||
There is no way to get the last value in our `list`. We also can't "go back".
|
||||
|
||||
So what we can do is to first go through the items in the direct order and rememeber them in an array, and then output what we remembered in the reverse order:
|
||||
So what we can do is to first go through the items in the direct order and remember them in an array, and then output what we remembered in the reverse order:
|
||||
|
||||
```js run
|
||||
let list = {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -458,7 +458,7 @@ If we don't catch the error there, then, as usual, it falls through to the outer
|
|||
|
||||
## Summary
|
||||
|
||||
- Generators are created by generator functions `function*(…) {…}`.
|
||||
- Generators are created by generator functions `function* f(…) {…}`.
|
||||
- Inside generators (only) there exists a `yield` operator.
|
||||
- The outer code and the generator may exchange results via `next/yield` calls.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue