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/4-data-types/01-object/article.md
+6-10Lines changed: 6 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,17 +1,13 @@
1
1
2
2
# Objects
3
3
4
-
As we know, there are 7 language types in Javascript.
4
+
As we know, there are 7 language types in Javascript. Six of them are called "primitive", because their values contain only a single thing (be it a string or a number or whatever).
5
5
6
-
Six of them are called "primitive", because their values contain only a single thing (be it a string or a number or whatever).
7
-
8
-
In contrast, objects are used to store *keyed collections* of various data and more complex entities.
9
-
10
-
In Javascript, objects penetrate almost every aspect of the language. So we must understand them first before going in-depth anywhere else.
6
+
In contrast, objects are used to store keyed collections of various data and more complex entities. In Javascript, objects penetrate almost every aspect of the language. So we must understand them first before going in-depth anywhere else.
11
7
12
8
[cut]
13
9
14
-
An object is defined with the figure brackets `{…}` with an optional list of "key: value" pairs. In programming that's sometimes called an "associative array" or a "hash".
10
+
An object can be created with figure brackets `{…}` with an optional list of "key: value" pairs. In programming that's sometimes called an "associative array" or a "hash".
15
11
16
12
We can imagine an object as a cabinet with signed files. Every piece of data is stored in it's file by the key. It's easy to find a file by it's name or add/remove a file.
17
13
@@ -144,14 +140,14 @@ let bag = {
144
140
alert( bag.apple ); // 5 if fruit="apple"
145
141
```
146
142
147
-
Here, the object `bag` is created with a property with the name from `fruit` variable and the value `5`. So, if a visitor enters `"apple"`, `bag` will become `{apple: 5}`.
143
+
Here, the value of `fruit` variable is used as the property name. So, if a visitor enters `"apple"`, `bag` will become `{apple: 5}`.
148
144
149
145
Essentially, that works the same as:
150
146
```js run
151
147
let fruit =prompt("Which fruit to buy?", "apple");
152
148
let bag = {};
153
149
154
-
// take property name from the fruit variable, assign 5 to it
150
+
// take property name from the fruit variable
155
151
bag[fruit] =5;
156
152
```
157
153
@@ -160,7 +156,7 @@ We can use more complex expressions inside square brackets. Anything that result
Copy file name to clipboardExpand all lines: 1-js/4-data-types/02-garbage-collection/article.md
+21-15Lines changed: 21 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,7 +12,9 @@ The main concept of memory management in Javascript is *reachability*.
12
12
13
13
Simply put, "reachable" values are those that are accessible now or in the future. They are guaranteed to be stored in memory.
14
14
15
-
1. There's a base set of inherently reachable values. For instance:
15
+
1. There's a base set of inherently reachable values, that cannot be deleted for obvious reasons.
16
+
17
+
For instance:
16
18
17
19
- Local variables and parameters of the current function.
18
20
- Variables and parameters for other functions on the current chain of nested calls.
@@ -38,9 +40,9 @@ let user = {
38
40
39
41

40
42
41
-
Here an on further pictures, arrows depict references. For instance, the global variable `"user"` references John (the object `{name: "John"}`). The `"name"` property is not a reference, it stores a primitive, so it's painted inside the object.
43
+
Here the arrow depicts an object reference. The global variable `"user"` references the object `{name: "John"}` (we'll call it John for brevity). The `"name"` property of John stores a primitive, so it's painted inside the object.
42
44
43
-
If the `user` is overwritten, the reference is lost:
45
+
If the value of `user` is overwritten, the reference is lost:
44
46
45
47
```js
46
48
user =null;
@@ -102,22 +104,24 @@ The resulting memory structure:
102
104
103
105

104
106
105
-
To activate garbage collection, let's remove two references:
107
+
As of now, all objects are reachable.
108
+
109
+
Now let's remove two references:
106
110
107
111
```js
108
112
deletefamily.father;
109
113
deletefamily.mother.husband;
110
114
```
111
115
112
-
Note that if the deletion of any single one of them would not lead to anything, because all objects would still be reachable.
116
+

117
+
118
+
It's not enough to delete any one of them, because all objects would still be reachable.
113
119
114
120
But if we delete both, then we can see that John has no incoming references any more:
115
121
116
122

117
123
118
-
Outgoing references do not matter. Only incoming ones can make an object reachable.
119
-
120
-
John, the former `family.father` is now unreachable and will be removed from the memory with all its data that also became unaccessible.
124
+
Outgoing references do not matter. Only incoming ones can make an object reachable. So, John is now unreachable and will be removed from the memory with all its data that also became unaccessible.
121
125
122
126
After garbage collection:
123
127
@@ -133,15 +137,15 @@ The source object is the same as above. Then:
133
137
family =null;
134
138
```
135
139
136
-
The result:
140
+
The in-memory picture becomes:
137
141
138
142

139
143
140
144
This example demonstrates how important the concept of reachability is.
141
145
142
-
It is clearly seen that John and Ann are still linked, both have incoming references. But it's not enough.
146
+
It's obvious that John and Ann are still linked, both have incoming references. But that's not enough.
143
147
144
-
The former `"family"` object has been unlinked from the root, there's no reference to it any more, so the whole island became unreachable and will be removed.
148
+
The former `"family"` object has been unlinked from the root, there's no reference to it any more, so the whole island becomes unreachable and will be removed.
145
149
146
150
## Internal algorithms
147
151
@@ -151,10 +155,12 @@ Regularly the following "garbage collection" steps are performed:
151
155
152
156
- The garbage collector takes roots and "marks" them.
153
157
- Then it visits and "marks" all references from them.
154
-
- Then it visits marked objects and marks *their* references, but the same object is not visited twice.
158
+
- Then it visits marked objects and marks *their* references. All visited objects are remembered, not to visit the same object twice in the future.
159
+
155
160
- ...And so on until there are unvisited references (reachable from the roots).
156
161
- All objects except marked ones are removed.
157
162
163
+
158
164
For instance, if our object structure looks like this:
159
165
160
166

@@ -182,10 +188,10 @@ Javascript engines apply many optimizations to it, to make it run faster and be
182
188
Some of the optimizations:
183
189
184
190
-**Generational collection** -- objects are split into two sets: "new ones" and "old ones". Many objects appear, do their job and die fast, so they can be cleaned up more aggressively. Those "new" that survive for long enough, become "old".
185
-
-**Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays. So the engine tries to split the job into pieces. Then pieces are executed one at a time. That requires some extra bookkeeping in-between them to stay consistent.
191
+
-**Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays. So the engine tries to split the job into pieces. Then pieces are executed one at a time. That requires some extra bookkeeping between them.
186
192
-**Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution.
187
193
188
-
In-depth understanding of these optimization is also possible, there's no magic, but it requires a lot of under-the-hood digging. Javascript engines implement garbage collection differently. And -- what's even more important, things change, so going really deep "in advance"is probably not worth that. Unless, of course, it is a matter of pure interest.
194
+
Detailed learning of these optimization is also possible, but it requires a lot of under-the-hood digging. Javascript engines implement garbage collection differently. And -- what's even more important, things change, so going really deep "in advance", without a real need is probably not worth that. Unless, of course, it is a matter of pure interest, then there will be some links for you below.
189
195
190
196
## Summary
191
197
@@ -197,7 +203,7 @@ The main things to know:
197
203
198
204
Modern engines implement advanced algorithms of garbage collection.
199
205
200
-
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). Also you'd better prepare yourself by learning how values are stored in V8. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, things are somewhat similar, but not the same.
206
+
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), and [V8 blog](http://v8project.blogspot.com/) also publishes articles about changes in memory management from time to time. Also you'd better prepare yourself by learning about V8 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.
201
207
202
208
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/4-data-types/03-object-methods/article.md
+14-76Lines changed: 14 additions & 76 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,12 +42,6 @@ A function that is the property of an object is called its *method*.
42
42
43
43
So, here we've got a method `sayHi` of the object `user`.
44
44
45
-
```smart header="Object-oriented programming"
46
-
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".
47
-
48
-
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. We will make use of OOP further when we get enough familarity with the language.
49
-
```
50
-
51
45
Of course, we could use a Function Declaration to add a method:
52
46
53
47
```js run
@@ -70,6 +64,11 @@ user.sayHi(); // Hello!
70
64
71
65
That would also work, but is longer. Also we get an "extra" function `sayHi` outside of the `user` object. Usually we don't want that.
72
66
67
+
```smart header="Object-oriented programming"
68
+
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".
69
+
70
+
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.
71
+
```
73
72
### Method shorthand
74
73
75
74
There exists a shorter syntax for methods in an object literal:
@@ -93,7 +92,7 @@ let user = {
93
92
};
94
93
```
95
94
96
-
As demonstrated, we can omit a colon with the word `"function"`.
95
+
As demonstrated, we can omit `"function"` and just write `sayHi()`.
97
96
98
97
To say the truth, the notations are not fully identical. There are subtle differences related to object inheritance (to be covered later), but for now they do not matter. In almost all cases the shorter syntax is preferred.
99
98
@@ -218,6 +217,14 @@ In non-strict mode (if you forgot `use strict`) the value of `this` in such case
218
217
219
218
Please note that usually a call of a function using `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.
220
219
220
+
```smart header="The consequences of unbound `this`"
221
+
If you come from another programming languages, then you are probably used to an idea of a "bound `this`", where methods defined in an object always have `this` referencing that object.
222
+
223
+
The idea of unbound, run-time evaluated `this` has both pluses and minuses. From one side, a function can be reused for different objects. From the other side, it's possible to occasionally loose `this` by making an improper call.
224
+
225
+
Here we are not to judge whether this language design decision is good or bad. We will understand how to work with it, how to get benefits and evade problems.
226
+
```
227
+
221
228
## Internals: Reference Type
222
229
223
230
An intricate method call can loose `this`, for instance:
@@ -290,75 +297,6 @@ Any other operation like assignment `hi = user.hi` discards the reference type a
290
297
291
298
So, as the result, the value of `this` is only passed the right way if the function is called directly using a dot `obj.method()` or square brackets `obj[method]()` syntax (they do the same here).
292
299
293
-
## Methods on primitives [todo: remove]
294
-
295
-
In JavaScript primitives (strings, numbers etc) also have methods, as if they were objects. Still, primitives are not objects, and this section explains the interesting design solution of Javascript that makes it possible.
296
-
297
-
Let's formulate the definitive distinction between primitives and objects.
298
-
299
-
A primitive
300
-
: Is a value of one of 6 primitive types: `string`, `number`, `boolean`, `symbol`, `null` and `undefined`.
301
-
302
-
An object
303
-
: Can be created with `{}`, for instance: `{name: "John", age: 30}`, is capable of storing multiple values as properties. There are other kinds of objects in JavaScript, e.g. functions are objects, there are objects that work with dates, errors and so on. They have different properties and methods.
304
-
305
-
But features come at a price!
306
-
307
-
Objects are "heavier" than primitives. They require additional resources to support the internal machinery. But properties and methods are useful in programming, Javascript engines try to optimize them, so the price is usually fair.
308
-
309
-
So here's the paradox faced by the creator of JavaScript:
310
-
311
-
- There are many things one would want to do with a primitive like a string or a number. Could be great to access them as methods.
312
-
- Primitives must be as fast and lightweight as possible.
313
-
314
-
The solution looks a little bit awkward, but here it is.
315
-
316
-
1. Primitives are still primitive. A single lightweight value, as described.
317
-
2. The language allows to access methods and properties of strings, numbers, booleans and symbols.
318
-
3. When it happens, a special "object wrapper" is created, it provides the functionality, and then is destroyed.
319
-
320
-
The "object wrappers" are different for each primitive type and are named specifically: `String`, `Number`, `Boolean` and `Symbol`. Thus they provide different sets of methods.
321
-
322
-
For instance, there exists a method [str.toUpperCase()](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) that returns the capitalized string.
323
-
324
-
Here's how it works:
325
-
326
-
```js run
327
-
let str ="Hello";
328
-
329
-
alert( str.toUpperCase() ); // HELLO
330
-
```
331
-
332
-
Simple, right? And here's what actually happens in `str.toUpperCase()`:
333
-
334
-
1. The string `str` is a primitive. So in the moment of accessing its property a special object is created that both knows the value of the string and has useful methods, like `toUpperCase()`.
335
-
2. That method runs and returns a new string (shown by `alert`).
336
-
3. The special object is destroyed, leaving the primitive `str` alone.
337
-
338
-
So, primitives can provide methods, but they still remain lightweight.
339
-
340
-
Of course, a JavaScript engine highly optimizes that process. Internally it may skip creation of the extra object at all. But it must adhere to the specification and behave as if it creates one.
341
-
342
-
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:
343
-
344
-
```js run
345
-
let n =1.23456;
346
-
347
-
alert( n.toFixed(2) ); // 1.23
348
-
```
349
-
350
-
We'll learn more specific methods in next chapters.
351
-
352
-
````warn header="null/undefined have no methods"
353
-
Special primitives `null` and `undefined` are exceptions. They have no corresponding "wrapper objects" and provide no methods. In a sense, they are "the most primitive".
354
-
355
-
An attempt to access a property of such value would give an error:
0 commit comments