fixed
This commit is contained in:
commit
121c264090
9 changed files with 31 additions and 31 deletions
|
@ -191,7 +191,7 @@ It supports two forms of syntax:
|
||||||
1. As an operator: `typeof x`.
|
1. As an operator: `typeof x`.
|
||||||
2. Function style: `typeof(x)`.
|
2. Function style: `typeof(x)`.
|
||||||
|
|
||||||
In other words, it works both with the brackets or without them. The result is the same.
|
In other words, it works both with parentheses or without them. The result is the same.
|
||||||
|
|
||||||
The call to `typeof x` returns a string with the type name:
|
The call to `typeof x` returns a string with the type name:
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ Just loop over the object and `return false` immediately if there's at least one
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function isEmpty(obj) {
|
function isEmpty(obj) {
|
||||||
for(let key in obj) {
|
for (let key in obj) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -4,10 +4,10 @@ let salaries = {
|
||||||
John: 100,
|
John: 100,
|
||||||
Ann: 160,
|
Ann: 160,
|
||||||
Pete: 130
|
Pete: 130
|
||||||
}
|
};
|
||||||
|
|
||||||
let sum = 0;
|
let sum = 0;
|
||||||
for(let key in salaries) {
|
for (let key in salaries) {
|
||||||
sum += salaries[key];
|
sum += salaries[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ For instance:
|
||||||
```smart header="Historical notes"
|
```smart header="Historical notes"
|
||||||
For historical reasons, methods `toString` or `valueOf` *should* return a primitive: if any of them returns an object, then there's no error, but that object is ignored (like if the method didn't exist).
|
For historical reasons, methods `toString` or `valueOf` *should* return a primitive: if any of them returns an object, then there's no error, but that object is ignored (like if the method didn't exist).
|
||||||
|
|
||||||
In contrast, `Symbol.toPrimitive` *must* return an primitive, otherwise there will be an error.
|
In contrast, `Symbol.toPrimitive` *must* return a primitive, otherwise, there will be an error.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
|
@ -70,7 +70,7 @@ So primitives can provide methods, but they still remain lightweight.
|
||||||
|
|
||||||
The JavaScript engine highly optimizes this process. It may even skip the creation of the extra object at all. But it must still adhere to the specification and behave as if it creates one.
|
The JavaScript engine highly optimizes this process. It may even skip the creation of the extra object at all. But it must still adhere to the specification and behave as if it creates one.
|
||||||
|
|
||||||
A number has methods of it's own, for instance, [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) rounds the number to the given precision:
|
A number has methods of its own, for instance, [toFixed(n)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) rounds the number to the given precision:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
let n = 1.23456;
|
let n = 1.23456;
|
||||||
|
|
|
@ -249,10 +249,10 @@ Can we work around the problem? Sure, there're a number of ways:
|
||||||
2. We can temporarily turn numbers into integers for the maths and then revert it back. It works like this:
|
2. We can temporarily turn numbers into integers for the maths and then revert it back. It works like this:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
alert( (0.1*10 + 0.2*10) / 10 ); // 0.3
|
alert( (0.1 * 10 + 0.2 * 10) / 10 ); // 0.3
|
||||||
```
|
```
|
||||||
|
|
||||||
This works because when we do `0.1*10 = 1` and `0.2 * 10 = 2` then both numbers become integers, and there's no precision loss.
|
This works because when we do `0.1 * 10 = 1` and `0.2 * 10 = 2` then both numbers become integers, and there's no precision loss.
|
||||||
|
|
||||||
3. If we were dealing with a shop, then the most radical solution would be to store all prices in cents and use no fractions at all. But what if we apply a discount of 30%? In practice, totally evading fractions is rarely feasible, so the solutions above help avoid this pitfall.
|
3. If we were dealing with a shop, then the most radical solution would be to store all prices in cents and use no fractions at all. But what if we apply a discount of 30%? In practice, totally evading fractions is rarely feasible, so the solutions above help avoid this pitfall.
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ JavaScript doesn't trigger an error in such events. It does its best to fit the
|
||||||
````
|
````
|
||||||
|
|
||||||
```smart header="Two zeroes"
|
```smart header="Two zeroes"
|
||||||
Another funny consequence of the internal representation of numbers is the existance of two zeroes: `0` and `-0`.
|
Another funny consequence of the internal representation of numbers is the existence of two zeroes: `0` and `-0`.
|
||||||
|
|
||||||
That's because a sign is represented by a single bit, so every number can be positive or negative, including a zero.
|
That's because a sign is represented by a single bit, so every number can be positive or negative, including a zero.
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
The two most used data structures in JavaScript are `Object` and `Array`.
|
The two most used data structures in JavaScript are `Object` and `Array`.
|
||||||
|
|
||||||
Objects allow to pack many pieces of information into a single entity and arrays allow to store ordered collections. So we can make an object or an array and handle it as a single thing, maybe pass to a function call.
|
Objects allow us to pack many pieces of information into a single entity and arrays allow us to store ordered collections. So we can make an object or an array and handle it as a single entity, or maybe pass it to a function call.
|
||||||
|
|
||||||
*Destructuring assignment* is a special syntax that allows to "unpack" arrays or objects into a bunch of variables, as sometimes they are more convenient. Destructuring also works great with complex functions that have a lot of parameters, default values, and soon we'll see how these are handled too.
|
*Destructuring assignment* is a special syntax that allows us to "unpack" arrays or objects into a bunch of variables, as sometimes they are more convenient. Destructuring also works great with complex functions that have a lot of parameters, default values, and soon we'll see how these are handled too.
|
||||||
|
|
||||||
[cut]
|
[cut]
|
||||||
|
|
||||||
|
@ -34,9 +34,9 @@ let [firstName, surname] = "Ilya Kantor".split(' ');
|
||||||
```
|
```
|
||||||
|
|
||||||
````smart header="\"Destructuring\" does not mean \"destructive\""
|
````smart header="\"Destructuring\" does not mean \"destructive\""
|
||||||
That's called "destructuring assignment", because it "destructurizes" by copying items into variables. But the array itself is not modified.
|
It's called "destructuring assignment", because it "destructurizes" by copying items into variables. But the array itself is not modified.
|
||||||
|
|
||||||
That's just a shorter way to write:
|
It's just a shorter way to write:
|
||||||
```js
|
```js
|
||||||
// let [firstName, surname] = arr;
|
// let [firstName, surname] = arr;
|
||||||
let firstName = arr[0];
|
let firstName = arr[0];
|
||||||
|
@ -56,12 +56,12 @@ let [, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
|
||||||
alert( title ); // Consul
|
alert( title ); // Consul
|
||||||
```
|
```
|
||||||
|
|
||||||
In the code above, the first and second elements of the array are skipped, the third one is assigned to `title`, and the rest is also skipped.
|
In the code above, although the first and second elements of the array are skipped, the third one is assigned to `title`, and the rest are also skipped.
|
||||||
````
|
````
|
||||||
|
|
||||||
````smart header="Works with any iterable on the right-side"
|
````smart header="Works with any iterable on the right-side"
|
||||||
|
|
||||||
...Actually, we can use it with any iterable, not only an array:
|
...Actually, we can use it with any iterable, not only arrays:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
let [a, b, c] = "abc"; // ["a", "b", "c"]
|
let [a, b, c] = "abc"; // ["a", "b", "c"]
|
||||||
|
@ -87,7 +87,7 @@ alert(user.name); // Ilya
|
||||||
|
|
||||||
````smart header="Looping with .entries()"
|
````smart header="Looping with .entries()"
|
||||||
|
|
||||||
In the previous chapter we saw [Object.entries(obj)](mdn:js/Object/entries) method.
|
In the previous chapter we saw the [Object.entries(obj)](mdn:js/Object/entries) method.
|
||||||
|
|
||||||
We can use it with destructuring to loop over keys-and-values of an object:
|
We can use it with destructuring to loop over keys-and-values of an object:
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ for(let [key, value] of user.entries()) {
|
||||||
````
|
````
|
||||||
### The rest '...'
|
### The rest '...'
|
||||||
|
|
||||||
If we want not just to get first values, but also to gather all that follows -- we can add one more parameter that gets "the rest" using the three dots `"..."`:
|
If we want not just to get first values, but also to gather all that follows -- we can add one more parameter that gets "the rest" using three dots `"..."`:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
let [name1, name2, *!*...rest*/!*] = ["Julius", "Caesar", *!*"Consul", "of the Roman Republic"*/!*];
|
let [name1, name2, *!*...rest*/!*] = ["Julius", "Caesar", *!*"Consul", "of the Roman Republic"*/!*];
|
||||||
|
@ -136,11 +136,11 @@ alert(rest.length); // 2
|
||||||
*/!*
|
*/!*
|
||||||
```
|
```
|
||||||
|
|
||||||
The value of `rest` is the array of the remaining array elements. We can use any other variable name in place of `rest`, just make sure it has three dots before it and goes the last.
|
The value of `rest` is the array of the remaining array elements. We can use any other variable name in place of `rest`, just make sure it has three dots before it and goes last in the destructuring assignmemnt.
|
||||||
|
|
||||||
### Default values
|
### Default values
|
||||||
|
|
||||||
If there are fewer values in the array than variables in the assignment -- there will be no error, absent values are considered undefined:
|
If there are fewer values in the array than variables in the assignment, there will be no error. Absent values are considered undefined:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
*!*
|
*!*
|
||||||
|
@ -164,7 +164,7 @@ alert(surname); // Anonymous (default used)
|
||||||
|
|
||||||
Default values can be more complex expressions or even function calls. They are evaluated only if the value is not provided.
|
Default values can be more complex expressions or even function calls. They are evaluated only if the value is not provided.
|
||||||
|
|
||||||
For instance, here we use `prompt` function for two defaults. But it will only run only for the missing one:
|
For instance, here we use the `prompt` function for two defaults. But it will run only for the missing one:
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
// runs only prompt for surname
|
// runs only prompt for surname
|
||||||
|
@ -186,7 +186,7 @@ The basic syntax is:
|
||||||
let {var1, var2} = {var1:…, var2…}
|
let {var1, var2} = {var1:…, var2…}
|
||||||
```
|
```
|
||||||
|
|
||||||
We have an existing object at the right side, that we want to split into variables. To the left side contains a "pattern" for corresponding properties. In the simple case that's a list of variable names in `{...}`.
|
We have an existing object at the right side, that we want to split into variables. The left side contains a "pattern" for corresponding properties. In the simple case, that's a list of variable names in `{...}`.
|
||||||
|
|
||||||
For instance:
|
For instance:
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ alert(width); // 100
|
||||||
alert(height); // 200
|
alert(height); // 200
|
||||||
```
|
```
|
||||||
|
|
||||||
Properties `options.title`, `options.width` and `options.height` are assigned to the corresponding variables. The order does not matter, that works too:
|
Properties `options.title`, `options.width` and `options.height` are assigned to the corresponding variables. The order does not matter. This works too:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// changed the order of properties in let {...}
|
// changed the order of properties in let {...}
|
||||||
|
@ -258,7 +258,7 @@ alert(height); // 200
|
||||||
|
|
||||||
Just like with arrays or function parameters, default values can be any expressions or even function calls. They will be evaluated if the value is not provided.
|
Just like with arrays or function parameters, default values can be any expressions or even function calls. They will be evaluated if the value is not provided.
|
||||||
|
|
||||||
The code below asks for width, but not about the title.
|
The code below asks for width, but not the title.
|
||||||
|
|
||||||
```js run
|
```js run
|
||||||
let options = {
|
let options = {
|
||||||
|
@ -391,7 +391,7 @@ Finally, we have `width`, `height`, `item1`, `item2` and `title` from the defaul
|
||||||
|
|
||||||
That often happens with destructuring assignments. We have a complex object with many properties and want to extract only what we need.
|
That often happens with destructuring assignments. We have a complex object with many properties and want to extract only what we need.
|
||||||
|
|
||||||
Even like this:
|
Even here it happens:
|
||||||
```js
|
```js
|
||||||
// take size as a whole into a variable, ignore the rest
|
// take size as a whole into a variable, ignore the rest
|
||||||
let { size } = options;
|
let { size } = options;
|
||||||
|
@ -409,7 +409,7 @@ function showMenu(title = "Untitled", width = 200, height = 100, items = []) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The real-life problem is how to remember the order of arguments. Usually IDEs try to help us, especially if the code is well-documented, but still... Another problem is how to call a function when most parameters are ok by default.
|
In real-life the problem is how to remember the order of arguments. Usually IDEs try to help us, especially if the code is well-documented, but still... Another problem is how to call a function when most parameters are ok by default.
|
||||||
|
|
||||||
Like this?
|
Like this?
|
||||||
|
|
||||||
|
@ -498,7 +498,7 @@ In the code above, the whole arguments object is `{}` by default, so there's alw
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
- Destructuring assignment allows to instantly map an object or array into many variables.
|
- Destructuring assignment allows for instantly mapping an object or array onto many variables.
|
||||||
- The object syntax:
|
- The object syntax:
|
||||||
```js
|
```js
|
||||||
let {prop : varName = default, ...} = object
|
let {prop : varName = default, ...} = object
|
||||||
|
|
|
@ -24,7 +24,7 @@ describe("spy", function() {
|
||||||
let wrappedSum = spy(sum);
|
let wrappedSum = spy(sum);
|
||||||
|
|
||||||
assert.equal(wrappedSum(1, 2), 3);
|
assert.equal(wrappedSum(1, 2), 3);
|
||||||
assert(spy.calledWith(1, 2));
|
assert(sum.calledWith(1, 2));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ describe("spy", function() {
|
||||||
calc.wrappedSum = spy(calc.sum);
|
calc.wrappedSum = spy(calc.sum);
|
||||||
|
|
||||||
assert.equal(calculator.wrappedSum(1, 2), 3);
|
assert.equal(calculator.wrappedSum(1, 2), 3);
|
||||||
assert(spy.calledWith(1, 2));
|
assert(calc.sum.calledWith(1, 2));
|
||||||
assert(spy.calledOn(calculator));
|
assert(calc.sum.calledOn(calculator));
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -50,7 +50,7 @@ The process is called "bubbling", because events "bubble" from the inner element
|
||||||
```warn header="*Almost* all events bubble."
|
```warn header="*Almost* all events bubble."
|
||||||
The key word in this phrase is "almost".
|
The key word in this phrase is "almost".
|
||||||
|
|
||||||
For instance, a `focus` event does not bubble. There are other examples too, we'll meet them. But still it's an exception, rather then a rule, most events do bubble.
|
For instance, a `focus` event does not bubble. There are other examples too, we'll meet them. But still it's an exception, rather than a rule, most events do bubble.
|
||||||
```
|
```
|
||||||
|
|
||||||
## event.target
|
## event.target
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue