flushing my list of typos when reaching the Objects chapter

This commit is contained in:
Thierry Parmentelat 2017-05-12 10:28:56 +02:00
parent 27a491f265
commit 4121423fc0
9 changed files with 27 additions and 27 deletions

View file

@ -4,7 +4,7 @@ importance: 5
# Output every second # Output every second
Write a function `printNumbers(from, to)` that outputs a number every second, starting from `from` and ending with `two`. Write a function `printNumbers(from, to)` that outputs a number every second, starting from `from` and ending with `to`.
Make two variants of the solution. Make two variants of the solution.

View file

@ -158,7 +158,7 @@ The `setTimeout` above schedules next call right at the end of the current one `
Recursive `setTimeout` is more flexible method than `setInterval`. This way the next call may be scheduled differently, depending on the results of the current one. Recursive `setTimeout` is more flexible method than `setInterval`. This way the next call may be scheduled differently, depending on the results of the current one.
For instance, we need to write a service that each 5 seconds sends a request to server asking for data, but in case if the server is overloaded, it should increase the interval to 10, 20, 60 seconds... For instance, we need to write a service that each 5 seconds sends a request to server asking for data, but in case the server is overloaded, it should increase the interval to 10, 20, 40 seconds...
Here's the pseudocode: Here's the pseudocode:
```js ```js
@ -226,7 +226,7 @@ And here is the picture for recursive `setTimeout`:
That's because a new call is planned at the end of the previous one. That's because a new call is planned at the end of the previous one.
````smart header="Garbage collection" ````smart header="Garbage collection"
When a function is passed in `setInterval/setTimeout`, an internal reference is created to it and saved in the scheduler. It prevents the function form being garbage collected, even if there are no other references to it. When a function is passed in `setInterval/setTimeout`, an internal reference is created to it and saved in the scheduler. It prevents the function from being garbage collected, even if there are no other references to it.
```js ```js
// the function stays in memory until the scheduler calls it // the function stays in memory until the scheduler calls it
@ -391,7 +391,7 @@ For server-side JavaScript, that limitation does not exist, and there exist othe
Another benefit for in-browser scripts is that they can show a progress bar or something to the user. That's because the browser usually does all "repainting" after the script is complete. Another benefit for in-browser scripts is that they can show a progress bar or something to the user. That's because the browser usually does all "repainting" after the script is complete.
So if we do a single huge function then even it changes something, the changes are not reflected in the document till it finishes. So if we do a single huge function then even if it changes something, the changes are not reflected in the document till it finishes.
Here's the demo: Here's the demo:
```html run ```html run

View file

@ -6,7 +6,7 @@ importance: 5
Create a "throttling" decorator `throttle(f, ms)` -- that returns a wrapper, passing the call to `f` at maximum once per `ms` milliseconds. Those calls that fall into the "cooldown" period, are ignored. Create a "throttling" decorator `throttle(f, ms)` -- that returns a wrapper, passing the call to `f` at maximum once per `ms` milliseconds. Those calls that fall into the "cooldown" period, are ignored.
**The differnce from `debounce` -- if an ignored call is the last during the cooldown, then it executes at the end of the delay.** **The difference with `debounce` -- if an ignored call is the last during the cooldown, then it executes at the end of the delay.**
Let's check the real-life application to better understand that requirement and to see where it comes from. Let's check the real-life application to better understand that requirement and to see where it comes from.

View file

@ -8,7 +8,7 @@ JavaScript gives exceptional flexibility when dealing with functions. They can b
Let's say we have a function `slow(x)` which is CPU-heavy, but its results are stable. In other words, for the same `x` it always returns the same result. Let's say we have a function `slow(x)` which is CPU-heavy, but its results are stable. In other words, for the same `x` it always returns the same result.
If the function is called often, we may want to cache (remember) the results for different `x` to evade spending extra-time on recalculations. If the function is called often, we may want to cache (remember) the results for different `x` to avoid spending extra-time on recalculations.
But instead of adding that functionality into `slow()` we'll create a wrapper. As we'll see, there are many benefits of doing so. But instead of adding that functionality into `slow()` we'll create a wrapper. As we'll see, there are many benefits of doing so.
@ -110,11 +110,11 @@ alert( worker.slow(2) ); // Whoops! Error: Cannot read property 'someMethod' of
*/!* */!*
``` ```
The error occurs in the line `(*)` that tries to access `this.someMethod` and fails. Guess you can see, why? The error occurs in the line `(*)` that tries to access `this.someMethod` and fails. Can you see why?
The reason is that the wrapper calls the original function as `func(x)` in the line `(**)`. And, when called like this, the function gets `this = undefined`. The reason is that the wrapper calls the original function as `func(x)` in the line `(**)`. And, when called like that, the function gets `this = undefined`.
As if we run: We would observe a similar symptom if we tried to run:
```js ```js
let func = worker.slow; let func = worker.slow;
@ -133,7 +133,7 @@ The syntax is:
func.call(context, arg1, arg2, ...) func.call(context, arg1, arg2, ...)
``` ```
It runs the `func` providing the first argument as `this`, and the next as the arguments. It runs `func` providing the first argument as `this`, and the next as the arguments.
To put it simple, these two calls do almost the same: To put it simple, these two calls do almost the same:
```js ```js
@ -173,7 +173,7 @@ say.call( user, "Hello" ); // John: Hello
``` ```
For our case, we can use `call` in the wrapper to pass the context to the original function: In our case, we can use `call` in the wrapper to pass the context to the original function:
```js run ```js run
@ -210,7 +210,7 @@ alert( worker.slow(2) ); // works, doesn't call the original (cached)
Now everything is fine. Now everything is fine.
To put all clear, let's see more deeply how `this` is passed along: To make it all clear, let's see more deeply how `this` is passed along:
1. After the decoration `worker.slow` is now the wrapper `function (x) { ... }`. 1. After the decoration `worker.slow` is now the wrapper `function (x) { ... }`.
2. So when `worker.slow(2)` is executed, the wrapper gets `2` as an argument and `this=worker` (it's the object before dot). 2. So when `worker.slow(2)` is executed, the wrapper gets `2` as an argument and `this=worker` (it's the object before dot).
@ -305,11 +305,11 @@ If we look more closely, there's a minor difference between such uses of `call`
- The spread operator `...` allows to pass *iterable* `args` as the list to `call`. - The spread operator `...` allows to pass *iterable* `args` as the list to `call`.
- The `apply` accepts only *array-like* `args`. - The `apply` accepts only *array-like* `args`.
So, these calls complement to each other. Where we expect an iterable, `call` works, where we expect an array-like, `apply` works. So, these calls complement each other. Where we expect an iterable, `call` works, where we expect an array-like, `apply` works.
And if `args` is both iterable and array-like, like a real array, then we technically could use any of them, but `apply` will probably be faster, because it's a single operation. Most JavaScript engines internally optimize is better than a pair `call + spread`. And if `args` is both iterable and array-like, like a real array, then we technically could use any of them, but `apply` will probably be faster, because it's a single operation. Most JavaScript engines internally optimize is better than a pair `call + spread`.
One of most important uses of `apply` is passing the call to another function, like this: One of the most important uses of `apply` is passing the call to another function, like this:
```js ```js
let wrapper = function() { let wrapper = function() {
@ -438,7 +438,7 @@ So, technically it takes `this` and joins `this[0]`, `this[1]` ...etc together.
*Decorator* is a wrapper around a function that alters its behavior. The main job is still carried out by the function. *Decorator* is a wrapper around a function that alters its behavior. The main job is still carried out by the function.
It is generally safe to replace a function or a method with decorated one, except for one little thing. If the original function had properties on it, like `func.calledCount` or whatever, then the decorated one will not provide them. Because that is a wrapper. So one need to be careful if he uses them. Some decorators provide their own properties. It is generally safe to replace a function or a method with a decorated one, except for one little thing. If the original function had properties on it, like `func.calledCount` or whatever, then the decorated one will not provide them. Because that is a wrapper. So one need to be careful if one uses them. Some decorators provide their own properties.
Decorators can be seen as "features" or "aspects" that can be added to a function. We can add one or add many. And all this without changing its code! Decorators can be seen as "features" or "aspects" that can be added to a function. We can add one or add many. And all this without changing its code!
@ -458,4 +458,4 @@ let wrapper = function() {
We also saw an example of *method borrowing* when we take a method from an object and `call` it in the context of another object. It is quite common to take array methods and apply them to arguments. The alternative is to use rest parameters object that is a real array. We also saw an example of *method borrowing* when we take a method from an object and `call` it in the context of another object. It is quite common to take array methods and apply them to arguments. The alternative is to use rest parameters object that is a real array.
There are many decorators there in the wilds. Check how well you got them by solving the tasks of this chapter. There are many decorators there in the wild. Check how well you got them by solving the tasks of this chapter.

View file

@ -10,6 +10,6 @@ f = f.bind( {name: "John"} ).bind( {name: "Pete"} );
f(); // John f(); // John
``` ```
The exotic [bound function](https://tc39.github.io/ecma262/#sec-bound-function-exotic-objects) object returned by `f.bind(...)` remembers the context (and arguments if provided) only at the creation time. The exotic [bound function](https://tc39.github.io/ecma262/#sec-bound-function-exotic-objects) object returned by `f.bind(...)` remembers the context (and arguments if provided) only at creation time.
A function cannot be re-bound. A function cannot be re-bound.

View file

@ -2,7 +2,7 @@ importance: 5
--- ---
# Ask loosing this # Ask losing this
The call to `askPassword()` in the code below should check the password and then call `user.loginOk/loginFail` depending on the answer. The call to `askPassword()` in the code below should check the password and then call `user.loginOk/loginFail` depending on the answer.

View file

@ -5,15 +5,15 @@ libs:
# Function binding # Function binding
When using `setTimeout` with object methods or passing object methods along, there's a known problem: "loosing `this`". When using `setTimeout` with object methods or passing object methods along, there's a known problem: "losing `this`".
Suddenly, `this` just stops working right. The situation is typical for novice developers, but happens with experienced ones as well. Suddenly, `this` just stops working right. The situation is typical for novice developers, but happens with experienced ones as well.
[cut] [cut]
## Loosing "this" ## Losing "this"
We already know that in JavaScript it's easy to loose `this`. Once a method is passed somewhere separately from the object -- `this` is lost. We already know that in JavaScript it's easy to lose `this`. Once a method is passed somewhere separately from the object -- `this` is lost.
Here's how it may happen with `setTimeout`: Here's how it may happen with `setTimeout`:
@ -72,7 +72,7 @@ setTimeout(() => user.sayHi(), 1000); // Hello, John!
Looks fine, but a slight vulnerability appears in our code structure. Looks fine, but a slight vulnerability appears in our code structure.
What is before `setTimeout` triggers (there's one second delay!) `user` changes value? Then, suddenly, the it will call the wrong object! What if before `setTimeout` triggers (there's one second delay!) `user` changes value? Then, suddenly, the it will call the wrong object!
```js run ```js run

View file

@ -105,7 +105,7 @@ The result of `partial(func[, arg1, arg2...])` call is a wrapper `(*)` that call
- Then gives it `...argsBound` -- arguments from the `partial` call (`"10:00"`) - Then gives it `...argsBound` -- arguments from the `partial` call (`"10:00"`)
- Then gives it `...args` -- arguments given to the wrapper (`"Hello"`) - Then gives it `...args` -- arguments given to the wrapper (`"Hello"`)
So easy to do it the spread operator, right? So easy to do it with the spread operator, right?
Also there's a ready [_.partial](https://lodash.com/docs#partial) implementation from lodash library. Also there's a ready [_.partial](https://lodash.com/docs#partial) implementation from lodash library.
@ -160,7 +160,7 @@ function curry(f) {
Advanced currying allows both to keep the function callable normally and to get partials easily. To understand the benefits we definitely need a worthy real-life example. Advanced currying allows both to keep the function callable normally and to get partials easily. To understand the benefits we definitely need a worthy real-life example.
For instance, we have the logging function `log(date, importance, message)` that formats and output the information. In real projects such functions also have many other useful features like: sending it over the network or filtering: For instance, we have the logging function `log(date, importance, message)` that formats and outputs the information. In real projects such functions also have many other useful features like: sending it over the network or filtering:
```js ```js
function log(date, importance, message) { function log(date, importance, message) {
@ -205,7 +205,7 @@ todayDebug("message"); // [HH:mm] DEBUG message
``` ```
So: So:
1. We didn't loose anything after currying: `log` is still callable normally. 1. We didn't lose anything after currying: `log` is still callable normally.
2. We were able to generate partial functions that are convenient in many cases. 2. We were able to generate partial functions that are convenient in many cases.
## Advanced curry implementation ## Advanced curry implementation

View file

@ -125,4 +125,4 @@ Arrow functions:
- Can't be called with `new`. - Can't be called with `new`.
- (They also don't have `super`, but we didn't study it. Will be in the chapter <info:class-inheritance>). - (They also don't have `super`, but we didn't study it. Will be in the chapter <info:class-inheritance>).
That's because they are meant for short pieces of code that does not have the own "context", but rather works in the current one. And they really shine in that use case. That's because they are meant for short pieces of code that does not have their own "context", but rather works in the current one. And they really shine in that use case.