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/01-getting-started/1-intro/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
@@ -26,7 +26,7 @@ Different engines have different "codenames". For example:
26
26
27
27
-[V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) -- in Chrome and Opera.
28
28
-[SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) -- in Firefox.
29
-
- ...There are other codenames like "Chakra" for IE, "ChakraCore" for Microsoft Edge, "Nitro" and "SquirrelFish" for Safari, etc.
29
+
- ...There are other codenames like "Chakra" for IE, "JavaScriptCore", "Nitro" and "SquirrelFish" for Safari, etc.
30
30
31
31
The terms above are good to remember because they are used in developer articles on the internet. We'll use them too. For instance, if "a feature X is supported by V8", then it probably works in Chrome and Opera.
Copy file name to clipboardExpand all lines: 1-js/02-first-steps/02-structure/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
@@ -46,7 +46,7 @@ alert(3 +
46
46
+2);
47
47
```
48
48
49
-
The code outputs `6` because JavaScript does not insert semicolons here. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an "incomplete expression", so the semicolon is not required. And in this case that works as intended.
49
+
The code outputs `6` because JavaScript does not insert semicolons here. It is intuitively obvious that if the line ends with a plus `"+"`, then it is an "incomplete expression", so a semicolon there would be incorrect. And in this case, that works as intended.
50
50
51
51
**But there are situations where JavaScript "fails" to assume a semicolon where it is really needed.**
Copy file name to clipboardExpand all lines: 1-js/02-first-steps/05-types/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
@@ -64,7 +64,7 @@ Special numeric values formally belong to the "number" type. Of course they are
64
64
65
65
We'll see more about working with numbers in the chapter <info:number>.
66
66
67
-
## BigInt
67
+
## BigInt[#bigint-type]
68
68
69
69
In JavaScript, the "number" type cannot represent integer values larger than <code>(2<sup>53</sup>-1)</code> (that's `9007199254740991`), or less than <code>-(2<sup>53</sup>-1)</code> for negatives. It's a technical limitation caused by their internal representation.
Copy file name to clipboardExpand all lines: 1-js/02-first-steps/15-function-basics/article.md
+33-20Lines changed: 33 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,10 +20,10 @@ function showMessage() {
20
20
}
21
21
```
22
22
23
-
The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* between the parentheses (comma-separated, empty in the example above) and finally the code of the function, also named "the function body", between curly braces.
23
+
The `function` keyword goes first, then goes the *name of the function*, then a list of *parameters* between the parentheses (comma-separated, empty in the example above, we'll see examples later) and finally the code of the function, also named "the function body", between curly braces.
When the function is called in lines `(*)` and `(**)`, the given values are copied to local variables `from` and `text`. Then the function uses them.
156
154
157
155
Here'sonemoreexample:wehaveavariable`from`andpassittothefunction. Please note: the function changes `from`, but the change is not seen outside, because a function always gets a copy of the value:
When a value is passed as a function parameter, it's also called an *argument*.
176
+
177
+
In other words, to put these terms straight:
178
+
179
+
- A parameter is the variable listed inside the parentheses in the function declaration (it's a declaration time term)
180
+
- An argument is the value that is passed to the function when it is called (it's a call time term).
181
+
182
+
We declare functions listing their parameters, then call them passing arguments.
183
+
184
+
In the example above, one might say: "the function `sayMessage` is declared with two parameters, then called with two arguments: `from` and `"Hello"`".
185
+
186
+
178
187
## Default values
179
188
180
-
If a parameter is not provided, then its value becomes `undefined`.
189
+
If a function is called, but an argument is not provided, then the corresponding value becomes `undefined`.
181
190
182
191
For instance, the aforementioned function `showMessage(from, text)` can be called with a single argument:
183
192
184
193
```js
185
194
showMessage("Ann");
186
195
```
187
196
188
-
That's not an error. Such a call would output `"*Ann*: undefined"`. There's no `text`, so it's assumed that `text===undefined`.
197
+
That's not an error. Such a call would output `"*Ann*: undefined"`. As the value for `text` isn't passed, it becomes `undefined`.
189
198
190
-
If we want to use a "default" `text` in this case, then we can specify it after`=`:
199
+
We can specify the so-called "default" (to use if omitted) value for a parameter in the function declaration, using`=`:
191
200
192
201
```jsrun
193
202
functionshowMessage(from, *!*text="no text given"*/!*) {
@@ -211,19 +220,23 @@ function showMessage(from, text = anotherFunction()) {
211
220
```smartheader="Evaluation of default parameters"
212
221
InJavaScript, adefaultparameterisevaluatedeverytimethefunction is called without the respective parameter.
213
222
214
-
In the example above, `anotherFunction()` is called every time `showMessage()` is called without the `text` parameter.
223
+
In the example above, `anotherFunction()` isn't called at all, if the `text` parameter is provided.
224
+
225
+
On the other hand, it's independently called every time when `text` is missing.
215
226
```
216
227
217
228
### Alternative default parameters
218
229
219
-
Sometimes it makes sense to set default values for parameters not in the function declaration, but at a later stage, during its execution.
230
+
Sometimes it makes sense to assign default values for parameters not in the function declaration, but at a later stage.
220
231
221
-
To check for an omitted parameter, we can compare it with `undefined`:
232
+
We can check if the parameter is passed during the function execution, by comparing it with `undefined`:
222
233
223
234
```js run
224
235
function showMessage(text) {
236
+
// ...
237
+
225
238
*!*
226
-
if (text ===undefined) {
239
+
if (text ===undefined) {// if the parameter is missing
227
240
text ='empty message';
228
241
}
229
242
*/!*
@@ -234,21 +247,21 @@ function showMessage(text) {
234
247
showMessage(); // empty message
235
248
```
236
249
237
-
...Or we could use the `||` operator:
250
+
...Or we could use the `??` operator:
238
251
239
252
```js
240
-
// if text parameter is omitted or "" is passed, set it to 'empty'
241
253
functionshowMessage(text) {
254
+
// if text is undefined or otherwise falsy, set it to 'empty'
242
255
text = text ||'empty';
243
256
...
244
257
}
245
258
```
246
259
247
-
Modern JavaScript engines support the [nullish coalescing operator](info:nullish-coalescing-operator) `??`, it's better when falsy values, such as `0`, are considered regular:
260
+
Modern JavaScript engines support the [nullish coalescing operator](info:nullish-coalescing-operator) `??`, it's better when most falsy values, such as `0`, should be considered "normal":
248
261
249
262
```js run
250
-
// if there's no "count" parameter, show "unknown"
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/06-constructor-new/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,13 +64,14 @@ Now if we want to create other users, we can call `new User("Ann")`, `new User("
64
64
65
65
That's the main purpose of constructors -- to implement reusable object creation code.
66
66
67
-
Let's note once again -- technically, any function can be used as a constructor. That is: any function can be run with `new`, and it will execute the algorithm above. The "capital letter first" is a common agreement, to make it clear that a function is to be run with `new`.
67
+
Let's note once again -- technically, any function (except arrow functions, as they don't have `this`) can be used as a constructor. It can be run with `new`, and it will execute the algorithm above. The "capital letter first" is a common agreement, to make it clear that a function is to be run with `new`.
68
68
69
69
````smart header="new function() { ... }"
70
-
If we have many lines of code all about creation of a single complex object, we can wrap them in constructor function, like this:
70
+
If we have many lines of code all about creation of a single complex object, we can wrap them in an immediately called constructor function, like this:
71
71
72
72
```js
73
-
let user = new function() {
73
+
// create a function and immediately call it with new
74
+
let user = new function() {
74
75
this.name = "John";
75
76
this.isAdmin = false;
76
77
@@ -80,7 +81,7 @@ let user = new function() {
80
81
};
81
82
```
82
83
83
-
The constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code that constructs the single object, without future reuse.
84
+
This constructor can't be called again, because it is not saved anywhere, just created and called. So this trick aims to encapsulate the code that constructs the single object, without future reuse.
Copy file name to clipboardExpand all lines: 1-js/04-object-basics/09-object-toprimitive/article.md
+35-13Lines changed: 35 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,19 +3,36 @@
3
3
4
4
What happens when objects are added `obj1 + obj2`, subtracted `obj1 - obj2` or printed using `alert(obj)`?
5
5
6
-
In that case, objects are auto-converted to primitives, and then the operation is carried out.
6
+
JavaScript doesn't exactly allow to customize how operators work on objects. Unlike some other programming languages, such as Ruby or C++, we can't implement a special object method to handle an addition (or other operators).
7
+
8
+
In case of such operations, objects are auto-converted to primitives, and then the operation is carried out over these primitives and results in a primitive value.
9
+
10
+
That's an important limitation, as the result of `obj1 + obj2` can't be another object!
11
+
12
+
E.g. we can't make objects representing vectors or matrices (or archievements or whatever), add them and expect a "summed" object as the result. Such architectural feats are automatically "off the board".
13
+
14
+
So, because we can't do much here, there's no maths with objects in real projects. When it happens, it's usually because of a coding mistake.
15
+
16
+
In this chapter we'll cover how an object converts to primitive and how to customize it.
17
+
18
+
We have two purposes:
19
+
20
+
1. It will allow us to understand what's going on in case of coding mistakes, when such an operation happened accidentally.
21
+
2. There are exceptions, where such operations are possible and look good. E.g. subtracting or comparing dates (`Date` objects). We'll come across them later.
22
+
23
+
## Conversion rules
7
24
8
25
In the chapter <info:type-conversions> we've seen the rules for numeric, string and boolean conversions of primitives. But we left a gap for objects. Now, as we know about methods and symbols it becomes possible to fill it.
9
26
10
27
1. All objects are `true` in a boolean context. There are only numeric and string conversions.
11
28
2. The numeric conversion happens when we subtract objects or apply mathematical functions. For instance, `Date` objects (to be covered in the chapter <info:date>) can be subtracted, and the result of `date1 - date2` is the time difference between two dates.
12
29
3. As for the string conversion -- it usually happens when we output an object like `alert(obj)` and in similar contexts.
13
30
14
-
## ToPrimitive
15
-
16
31
We can fine-tune string and numeric conversion, using special object methods.
17
32
18
-
There are three variants of type conversion, so-called "hints", described in the [specification](https://tc39.github.io/ecma262/#sec-toprimitive):
33
+
There are three variants of type conversion, that happen in various situations.
34
+
35
+
They're called "hints", as described in the [specification](https://tc39.github.io/ecma262/#sec-toprimitive):
19
36
20
37
`"string"`
21
38
: For an object-to-string conversion, when we're doing an operation on an object that expects a string, like `alert`:
@@ -82,11 +99,14 @@ Let's start from the first method. There's a built-in symbol named `Symbol.toPri
82
99
83
100
```js
84
101
obj[Symbol.toPrimitive] = function(hint) {
85
-
// must return a primitive value
102
+
// here goes the code to convert this object to a primitive
103
+
// it must return a primitive value
86
104
// hint = one of "string", "number", "default"
87
105
};
88
106
```
89
107
108
+
If the method `Symbol.toPrimitive` exists, it's used for all hints, and no more methods are needed.
109
+
90
110
For instance, here `user` object implements it:
91
111
92
112
```js run
@@ -111,12 +131,12 @@ As we can see from the code, `user` becomes a self-descriptive string or a money
111
131
112
132
## toString/valueOf
113
133
114
-
Methods `toString` and `valueOf` come from ancient times. They are not symbols (symbols did not exist that long ago), but rather "regular" string-named methods. They provide an alternative "old-style" way to implement the conversion.
134
+
If there's no `Symbol.toPrimitive` then JavaScript tries to find methods`toString` and `valueOf`:
115
135
116
-
If there's no `Symbol.toPrimitive` then JavaScript tries to find them and try in the order:
136
+
- For the "string" hint: `toString`, and if it doesn't exist, then `valueOf` (so `toString` has the priority for stirng conversions).
137
+
- For other hints: `valueOf`, and if it doesn't exist, then `toString` (so `valueOf` has the priority for maths).
117
138
118
-
-`toString -> valueOf` for "string" hint.
119
-
-`valueOf -> toString` otherwise.
139
+
Methods `toString` and `valueOf` come from ancient times. They are not symbols (symbols did not exist that long ago), but rather "regular" string-named methods. They provide an alternative "old-style" way to implement the conversion.
120
140
121
141
These methods must return a primitive value. If `toString` or `valueOf` returns an object, then it's ignored (same as if there were no method).
So if we try to use an object as a string, like in an `alert` or so, then by default we see `[object Object]`.
138
158
139
-
And the default `valueOf` is mentioned here only for the sake of completeness, to avoid any confusion. As you can see, it returns the object itself, and so is ignored. Don't ask me why, that's for historical reasons. So we can assume it doesn't exist.
159
+
The default `valueOf` is mentioned here only for the sake of completeness, to avoid any confusion. As you can see, it returns the object itself, and so is ignored. Don't ask me why, that's for historical reasons. So we can assume it doesn't exist.
140
160
141
-
Let's implement these methods.
161
+
Let's implement these methods to customize the conversion.
142
162
143
163
For instance, here `user` does the same as above using a combination of `toString` and `valueOf` instead of `Symbol.toPrimitive`:
In the absence of `Symbol.toPrimitive` and `valueOf`, `toString` will handle all primitive conversions.
185
205
186
-
##Return types
206
+
### A conversion can return any primitive type
187
207
188
208
The important thing to know about all primitive-conversion methods is that they do not necessarily return the "hinted" primitive.
189
209
@@ -252,4 +272,6 @@ The conversion algorithm is:
252
272
3. Otherwise if hint is `"number"` or `"default"`
253
273
- try `obj.valueOf()` and `obj.toString()`, whatever exists.
254
274
255
-
In practice, it's often enough to implement only `obj.toString()` as a "catch-all" method for all conversions that return a "human-readable" representation of an object, for logging or debugging purposes.
275
+
In practice, it's often enough to implement only `obj.toString()` as a "catch-all" method for string conversions that should return a "human-readable" representation of an object, for logging or debugging purposes.
276
+
277
+
As for math operations, JavaScript doesn't provide a way to "override" them using methods, so real life projects rarely use them on objects.
Copy file name to clipboardExpand all lines: 1-js/05-data-types/03-string/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
@@ -526,7 +526,7 @@ Now it becomes obvious why `a > Z`.
526
526
The characters are compared by their numeric code. The greater code means that the character is greater. The code for `a` (97) is greater than the code for `Z` (90).
527
527
528
528
- All lowercase letters go after uppercase letters because their codes are greater.
529
-
- Some letters like `Ö` stand apart from the main alphabet. Here, it's code is greater than anything from `a` to `z`.
529
+
- Some letters like `Ö` stand apart from the main alphabet. Here, its code is greater than anything from `a` to `z`.
0 commit comments