Skip to content

Commit 9064e35

Browse files
committed
ok
1 parent eb49340 commit 9064e35

File tree

9 files changed

+188
-198
lines changed

9 files changed

+188
-198
lines changed

1-js/4-data-types/01-object/article.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11

22
# Objects
33

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).
55

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.
117

128
[cut]
139

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".
1511

1612
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.
1713

@@ -144,14 +140,14 @@ let bag = {
144140
alert( bag.apple ); // 5 if fruit="apple"
145141
```
146142

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}`.
148144

149145
Essentially, that works the same as:
150146
```js run
151147
let fruit = prompt("Which fruit to buy?", "apple");
152148
let bag = {};
153149

154-
// take property name from the fruit variable, assign 5 to it
150+
// take property name from the fruit variable
155151
bag[fruit] = 5;
156152
```
157153

@@ -160,7 +156,7 @@ We can use more complex expressions inside square brackets. Anything that result
160156
```js
161157
let fruit = 'apple';
162158
let bag = {
163-
[ 'apple' + 'Computers' ]: 5 // bag.appleComputers = 5
159+
['apple' + 'Computers']: 5 // bag.appleComputers = 5
164160
};
165161
```
166162

1-js/4-data-types/02-garbage-collection/article.md

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ The main concept of memory management in Javascript is *reachability*.
1212

1313
Simply put, "reachable" values are those that are accessible now or in the future. They are guaranteed to be stored in memory.
1414

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:
1618

1719
- Local variables and parameters of the current function.
1820
- Variables and parameters for other functions on the current chain of nested calls.
@@ -38,9 +40,9 @@ let user = {
3840

3941
![](memory-user-john.png)
4042

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.
4244

43-
If the `user` is overwritten, the reference is lost:
45+
If the value of `user` is overwritten, the reference is lost:
4446

4547
```js
4648
user = null;
@@ -102,22 +104,24 @@ The resulting memory structure:
102104

103105
![](family.png)
104106

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:
106110

107111
```js
108112
delete family.father;
109113
delete family.mother.husband;
110114
```
111115

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+
![](family-delete-refs.png)
117+
118+
It's not enough to delete any one of them, because all objects would still be reachable.
113119

114120
But if we delete both, then we can see that John has no incoming references any more:
115121

116122
![](family-no-father.png)
117123

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.
121125

122126
After garbage collection:
123127

@@ -133,15 +137,15 @@ The source object is the same as above. Then:
133137
family = null;
134138
```
135139

136-
The result:
140+
The in-memory picture becomes:
137141

138142
![](family-no-family.png)
139143

140144
This example demonstrates how important the concept of reachability is.
141145

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.
143147

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.
145149

146150
## Internal algorithms
147151

@@ -151,10 +155,12 @@ Regularly the following "garbage collection" steps are performed:
151155

152156
- The garbage collector takes roots and "marks" them.
153157
- 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+
155160
- ...And so on until there are unvisited references (reachable from the roots).
156161
- All objects except marked ones are removed.
157162

163+
158164
For instance, if our object structure looks like this:
159165

160166
![](garbage-collection-1.png)
@@ -182,10 +188,10 @@ Javascript engines apply many optimizations to it, to make it run faster and be
182188
Some of the optimizations:
183189

184190
- **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.
186192
- **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution.
187193

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.
189195

190196
## Summary
191197

@@ -197,7 +203,7 @@ The main things to know:
197203

198204
Modern engines implement advanced algorithms of garbage collection.
199205

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.
201207

202208
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.
203209

16 KB
Loading
37.6 KB
Loading

1-js/4-data-types/03-object-methods/article.md

Lines changed: 14 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ A function that is the property of an object is called its *method*.
4242

4343
So, here we've got a method `sayHi` of the object `user`.
4444

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-
5145
Of course, we could use a Function Declaration to add a method:
5246

5347
```js run
@@ -70,6 +64,11 @@ user.sayHi(); // Hello!
7064

7165
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.
7266

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+
```
7372
### Method shorthand
7473

7574
There exists a shorter syntax for methods in an object literal:
@@ -93,7 +92,7 @@ let user = {
9392
};
9493
```
9594

96-
As demonstrated, we can omit a colon with the word `"function"`.
95+
As demonstrated, we can omit `"function"` and just write `sayHi()`.
9796

9897
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.
9998

@@ -218,6 +217,14 @@ In non-strict mode (if you forgot `use strict`) the value of `this` in such case
218217

219218
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.
220219

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+
221228
## Internals: Reference Type
222229
223230
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
290297

291298
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).
292299

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:
356-
357-
```js run
358-
alert(null.test); // error
359-
````
360-
361-
362300
## Summary
363301

364302
[todo]

0 commit comments

Comments
 (0)