You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/02-garbage-collection/article.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -207,6 +207,6 @@ A general book "The Garbage Collection Handbook: The Art of Automatic Memory Man
207
207
208
208
If you are familiar with low-level programming, the more detailed information about V8 garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection).
209
209
210
-
[V8 blog](http://v8project.blogspot.com/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects.
210
+
[V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects.
211
211
212
212
In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language.
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/04-object-methods/article.md
+13-9Lines changed: 13 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -63,7 +63,7 @@ user.sayHi(); // Hello!
63
63
```smart header="Object-oriented programming"
64
64
When we write our code using objects to represent entities, that's called an [object-oriented programming](https://en.wikipedia.org/wiki/Object-oriented_programming), in short: "OOP".
65
65
66
-
OOP is a big thing, an interesting science of its own. How to choose the right entities? How to organize the interaction between them? That's architecture, and there are great books on that topic, like "Design Patterns: Elements of Reusable Object-Oriented Software" by E.Gamma, R.Helm, R.Johnson, J.Vissides or "Object-Oriented Analysis and Design with Applications" by G.Booch, and more.
66
+
OOP is a big thing, an interesting science of its own. How to choose the right entities? How to organize the interaction between them? That's architecture, and there are great books on that topic, like "Design Patterns: Elements of Reusable Object-Oriented Software" by E.Gamma, R.Helm, R.Johnson, J.Vissides or "Object-Oriented Analysis and Design with Applications" by G.Booch, and more.
67
67
```
68
68
### Method shorthand
69
69
@@ -72,14 +72,14 @@ There exists a shorter syntax for methods in an object literal:
72
72
```js
73
73
// these objects do the same
74
74
75
-
letuser = {
75
+
user = {
76
76
sayHi:function() {
77
77
alert("Hello");
78
78
}
79
79
};
80
80
81
81
// method shorthand looks better, right?
82
-
letuser = {
82
+
user = {
83
83
*!*
84
84
sayHi() { // same as "sayHi: function()"
85
85
*/!*
@@ -166,7 +166,7 @@ If we used `this.name` instead of `user.name` inside the `alert`, then the code
166
166
167
167
## "this" is not bound
168
168
169
-
In JavaScript, "this" keyword behaves unlike most other programming languages. First, it can be used in any function.
169
+
In JavaScript, "this" keyword behaves unlike most other programming languages. It can be used in any function.
170
170
171
171
There's no syntax error in the code like that:
172
172
@@ -176,9 +176,9 @@ function sayHi() {
176
176
}
177
177
```
178
178
179
-
The value of `this` is evaluated during the run-time. And it can be anything.
179
+
The value of `this` is evaluated during the run-time, depending on the context. And it can be anything.
180
180
181
-
For instance, the same function may have different "this" when called from different objects:
181
+
For instance, here the same function is assigned to two different objects and has different "this" in the calls:
admin['f'](); // Admin (dot or square brackets access the method – doesn't matter)
203
203
```
204
204
205
-
Actually, we can call the function without an object at all:
205
+
The rule is simple: if `obj.f()` is called, then `this` is `obj` during the call of `f`. So it's either `user` or `admin` in the example above.
206
+
207
+
````smart header="Calling without an object: `this == undefined`"
208
+
We can even call the function without an object at all:
206
209
207
210
```js run
208
211
functionsayHi() {
@@ -216,7 +219,8 @@ In this case `this` is `undefined` in strict mode. If we try to access `this.nam
216
219
217
220
In non-strict mode the value of `this` in such case will be the *global object* (`window` in a browser, we'll get to it later in the chapter [](info:global-object)). This is a historical behavior that `"use strict"` fixes.
218
221
219
-
Please note that usually a call of a function that uses `this` without an object is not normal, but rather a programming mistake. If a function has `this`, then it is usually meant to be called in the context of an object.
222
+
Usually such call is an programming error. If there's `this` inside a function, it expects to be called in an object context.
223
+
````
220
224
221
225
```smart header="The consequences of unbound `this`"
222
226
If you come from another programming language, then you are probably used to the idea of a "bound `this`", where methods defined in an object always have `this` referencing that object.
Copy file name to clipboardExpand all lines: 1-js/05-data-types/11-json/article.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -66,7 +66,7 @@ alert(json);
66
66
67
67
The method `JSON.stringify(student)` takes the object and converts it into a string.
68
68
69
-
The resulting `json` string is a called *JSON-encoded* or *serialized* or *stringified* or *marshalled* object. We are ready to send it over the wire or put into a plain data store.
69
+
The resulting `json` string is called a*JSON-encoded* or *serialized* or *stringified* or *marshalled* object. We are ready to send it over the wire or put into a plain data store.
70
70
71
71
72
72
Please note that a JSON-encoded object has several important differences from the object literal:
Copy file name to clipboardExpand all lines: 1-js/08-prototypes/02-function-prototype/article.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -162,7 +162,7 @@ Everything is quite simple, just few notes to make things clear:
162
162
163
163
- The `F.prototype` property is not the same as `[[Prototype]]`. The only thing `F.prototype` does: it sets `[[Prototype]]` of new objects when `new F()` is called.
164
164
- The value of `F.prototype` should be either an object or null: other values won't work.
165
-
- The `"prototype"` property only has such a special effect when is set to a constructor function, and invoked with `new`.
165
+
- The `"prototype"` property only has such a special effect when set on a constructor function, and invoked with `new`.
166
166
167
167
On regular objects the `prototype` is nothing special:
Copy file name to clipboardExpand all lines: 1-js/09-classes/01-class/article.md
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -64,7 +64,7 @@ The notation here is not to be confused with object literals. Within the class,
64
64
65
65
## What is a class?
66
66
67
-
So, what exactly is a `class`? That's not an entirely new language-level entity, as one might think.
67
+
So, what exactly is a `class`? That's not an entirely new language-level entity, as one might think.
68
68
69
69
Let's unveil any magic and see what a class really is. That'll help in understanding many complex aspects.
70
70
@@ -91,7 +91,7 @@ What `class User {...}` construct really does is:
91
91
92
92
Afterwards, for new objects, when we call a method, it's taken from the prototype, just as described in the chapter <info:function-prototype>. So `new User` object has access to class methods.
93
93
94
-
We can illustrate the result of `class User` as:
94
+
We can illustrate the result of `class User`declaration as:
95
95
96
96

97
97
@@ -198,7 +198,8 @@ Similar to Named Function Expressions, class expressions may or may not have a n
198
198
If a classexpression has a name, it's visible inside the class only:
199
199
200
200
```js run
201
-
// "Named Class Expression" (alas, no such term, but that's what's going on)
201
+
// "Named Class Expression"
202
+
// (no such term in the spec, but that's similar to Named Function Expression)
202
203
let User =class*!*MyClass*/!* {
203
204
sayHi() {
204
205
alert(MyClass); // MyClass is visible only inside the class
@@ -268,7 +269,7 @@ alert(user.name); // John
268
269
user =newUser(""); // Name too short.
269
270
```
270
271
271
-
Internally, getters and setters are created on`User.prototype`, like this:
272
+
The class declaration creates getters and setters in`User.prototype`, like this:
Copy file name to clipboardExpand all lines: 1-js/10-error-handling/2-custom-errors/article.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ Our errors should support basic error properties like `message`, `name` and, pre
6
6
7
7
JavaScript allows to use `throw` with any argument, so technically our custom error classes don't need to inherit from `Error`. But if we inherit, then it becomes possible to use `obj instanceof Error` to identify error objects. So it's better to inherit from it.
8
8
9
-
As we build our application, our own errors naturally form a hierarchy, for instance `HttpTimeoutError` may inherit from `HttpError`, and so on.
9
+
As the application grows, our own errors naturally form a hierarchy, for instance `HttpTimeoutError` may inherit from `HttpError`, and so on.
10
10
11
11
## Extending Error
12
12
@@ -126,7 +126,7 @@ We could also look at `err.name`, like this:
126
126
127
127
The `instanceof` version is much better, because in the future we are going to extend `ValidationError`, make subtypes of it, like `PropertyRequiredError`. And `instanceof` check will continue to work for new inheriting classes. So that's future-proof.
128
128
129
-
Also it's important that if `catch` meets an unknown error, then it rethrows it in the line `(**)`. The `catch` only knows how to handle validation and syntax errors, other kinds (due to a typo in the code or such) should fall through.
129
+
Also it's important that if `catch` meets an unknown error, then it rethrows it in the line `(**)`. The `catch`block only knows how to handle validation and syntax errors, other kinds (due to a typo in the code or other unknown ones) should fall through.
130
130
131
131
## Further inheritance
132
132
@@ -185,7 +185,7 @@ try {
185
185
186
186
The new class `PropertyRequiredError` is easy to use: we only need to pass the property name: `newPropertyRequiredError(property)`. The human-readable `message` is generated by the constructor.
187
187
188
-
Please note that `this.name` in `PropertyRequiredError` constructor is again assigned manually. That may become a bit tedious -- to assign `this.name=<classname>`when creating each custom error. But there's a way out. We can make our own "basic error" class that removes this burden from our shoulders by using `this.constructor.name` for `this.name` in the constructor. And then inherit from it.
188
+
Please note that `this.name` in `PropertyRequiredError` constructor is again assigned manually. That may become a bit tedious -- to assign `this.name=<classname>`in every custom error class. But there's a way out. We can make our own "basic error" class that removes this burden from our shoulders by using `this.constructor.name` for `this.name` in its constructor. And then inherit all ours custom errors from it.
189
189
190
190
Let's call it `MyError`.
191
191
@@ -218,7 +218,7 @@ Now custom errors are much shorter, especially `ValidationError`, as we got rid
218
218
219
219
## Wrapping exceptions
220
220
221
-
The purpose of the function `readUser` in the code above is "to read the user data", right? There may occur different kinds of errors in the process. Right now we have `SyntaxError` and `ValidationError`, but in the future `readUser` function may grow: the new code will probably generate other kinds of errors.
221
+
The purpose of the function `readUser` in the code above is "to read the user data", right? There may occur different kinds of errors in the process. Right now we have `SyntaxError` and `ValidationError`, but in the future `readUser` function may grow and probably generate other kinds of errors.
222
222
223
223
The code which calls `readUser` should handle these errors. Right now it uses multiple `if` in the `catch` block to check for different error types and rethrow the unknown ones. But if `readUser` function generates several kinds of errors -- then we should ask ourselves: do we really want to check for all error types one-by-one in every code that calls `readUser`?
224
224
@@ -303,5 +303,5 @@ The approach is called "wrapping exceptions", because we take "low level excepti
303
303
## Summary
304
304
305
305
- We can inherit from `Error` and other built-in error classes normally, just need to take care of `name` property and don't forget to call `super`.
306
-
- Most of the time, we should use `instanceof` to check for particular errors. It also works with inheritance. But sometimes we have an error object coming from the 3rd-party library and there's no easy way to get the class. Then `name` property can be used for such checks.
307
-
- Wrapping exceptions is a widespread technique when a function handles low-level exceptions and makes a higher-level object to report about the errors. Low-level exceptions sometimes become properties of that object like `err.cause` in the examples above, but that's not strictly required.
306
+
- We can use `instanceof` to check for particular errors. It also works with inheritance. But sometimes we have an error object coming from the 3rd-party library and there's no easy way to get the class. Then `name` property can be used for such checks.
307
+
- Wrapping exceptions is a widespread technique: a function handles low-level exceptions and creates higher-level errors instead of various low-level ones. Low-level exceptions sometimes become properties of that object like `err.cause` in the examples above, but that's not strictly required.
Copy file name to clipboardExpand all lines: 1-js/11-async/07-microtask-queue/article.md
+11-9Lines changed: 11 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,9 +3,9 @@
3
3
4
4
Promise handlers `.then`/`.catch`/`.finally` are always asynchronous.
5
5
6
-
Even when a Promise is immediately resolved, the code on the lines *below*your `.then`/`.catch`/`.finally` will still execute first.
6
+
Even when a Promise is immediately resolved, the code on the lines *below*`.then`/`.catch`/`.finally` will still execute before these handlers .
7
7
8
-
Here's the code that demonstrates it:
8
+
Here's the demo:
9
9
10
10
```js run
11
11
let promise =Promise.resolve();
@@ -21,7 +21,7 @@ That's strange, because the promise is definitely done from the beginning.
21
21
22
22
Why did the `.then` trigger afterwards? What's going on?
23
23
24
-
# Microtasks
24
+
##Microtasks
25
25
26
26
Asynchronous tasks need proper management. For that, the standard specifies an internal queue `PromiseJobs`, more often referred to as "microtask queue" (v8 term).
27
27
@@ -54,9 +54,11 @@ Now the order is as intended.
54
54
55
55
## Event loop
56
56
57
-
In-browser JavaScript, as well as Node.js, is based on an *event loop*.
57
+
In-browser JavaScript execution flow, as well as Node.js, is based on an *event loop*.
58
58
59
-
"Event loop" is a process when the engine sleeps and waits for events, then reacts on those and sleeps again.
59
+
"Event loop" is a process when the engine sleeps and waits for events. When they occur - handles them and sleeps again.
60
+
61
+
Events may come either comes from external sources, like user actions, or just as the end signal of an internal task.
60
62
61
63
Examples of events:
62
64
-`mousemove`, a user moved their mouse.
@@ -120,14 +122,14 @@ Promise.resolve()
120
122
121
123
Naturally, `promise` shows up first, because `setTimeout` macrotask awaits in the less-priority macrotask queue.
122
124
123
-
As a logical consequence, macrotasks are handled only when promises give the engine a "free time". So if we have a promise chain that doesn't wait for anything, then things like `setTimeout` or event handlers can never get in the middle.
125
+
As a logical consequence, macrotasks are handled only when promises give the engine a "free time". So if we have a chain of promise handlers that don't wait for anything, execute right one after another, then a `setTimeout`(or a user action handler) can never run in-between them.
124
126
125
127
126
128
## Unhandled rejection
127
129
128
130
Remember "unhandled rejection" event from the chapter <info:promise-error-handling>?
129
131
130
-
Now, with the understanding of microtasks, we can formalize it.
132
+
Now we can describe how JavaScript finds out that a rejection was not handled.
131
133
132
134
**"Unhandled rejection" is when a promise error is not handled at the end of the microtask queue.**
Now the unhandled rejection appears again. Why? Because `unhandledrejection`triggers when the microtask queue is complete. The engine examines promises and, if any of them is in "rejected" state, then the event is generated.
172
+
Now the unhandled rejection appears again. Why? Because `unhandledrejection`is generated when the microtask queue is complete. The engine examines promises and, if any of them is in "rejected" state, then the event triggers.
171
173
172
174
In the example, the `.catch` added by `setTimeout` triggers too, of course it does, but later, after `unhandledrejection` has already occurred.
173
175
174
176
## Summary
175
177
176
178
- Promise handling is always asynchronous, as all promise actions pass through the internal "promise jobs" queue, also called "microtask queue" (v8 term).
177
179
178
-
**So, `.then/catch/finally` are called after the current code is finished.**
180
+
**So, `.then/catch/finally`handlers are called after the current code is finished.**
179
181
180
182
If we need to guarantee that a piece of code is executed after `.then/catch/finally`, it's best to add it into a chained `.then` call.
0 commit comments