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-object-basics/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
@@ -490,13 +490,13 @@ alert(*!*user.name*/!*); // 'Pete', changes are seen from the "user" reference
490
490
491
491
The example above demonstrates that there is only one object. Like if we had a cabinet with two keys and used one of them (`admin`) to get into it -- later using the other one (`user`) we will see things modified.
492
492
493
-
494
-
495
493
### Comparison by reference
496
494
497
-
The equality `==` and strict equality `===` operators for objects work exactly the same, simple way.
495
+
The equality `==` and strict equality `===` operators for objects work exactly the same.
496
+
497
+
**Two objects are equal only if they are the same object.**
498
498
499
-
**Two object variables are equal only when reference the same object.**
499
+
For instance, two variables reference the same object, they are equal:
500
500
501
501
```js run
502
502
let a = {};
@@ -506,9 +506,7 @@ alert( a == b ); // true, both variables reference the same object
506
506
alert( a === b ); // true
507
507
```
508
508
509
-
In all other cases objects are non-equal, even if their content is the same.
510
-
511
-
For instance:
509
+
And here two independent objects are not equal, even though both are empty:
512
510
513
511
```js run
514
512
let a = {};
@@ -517,9 +515,7 @@ let b = {}; // two independent objects
517
515
alert( a == b ); // false
518
516
```
519
517
520
-
That rule only applies to object vs object equality checks.
521
-
522
-
For other comparisons like whether an object less/greater than another object (`obj1 > obj2`) or for a comparison against a primitive `obj ==5`, objects are converted to primitives. We'll study how object conversions work very soon, but to say the truth, such comparisons occur very rarely in real code and usually are a result of a coding mistake.
518
+
For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj ==5`, objects are converted to primitives. We'll study how object conversions work very soon, but to say the truth, such comparisons occur very rarely in real code and usually are a result of a coding mistake.
Copy file name to clipboardExpand all lines: 1-js/4-object-basics/03-object-methods/article.md
-2Lines changed: 0 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -214,7 +214,6 @@ In this case `this` is `undefined` in strict mode. If we try to access `this.nam
214
214
215
215
In non-strict mode (if you forgot `use strict`) the value of `this` in such case will be the *global object* (`"window"` for browser, we'll study it later). This is just a historical thing that `"use strict"` fixes.
216
216
217
-
218
217
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.
219
218
220
219
```smart header="The consequences of unbound `this`"
@@ -224,7 +223,6 @@ The idea of unbound, run-time evaluated `this` has both pluses and minuses. From
224
223
225
224
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
225
```
227
-
228
226
## Internals: Reference Type
229
227
230
228
An intricate method call can loose `this`, for instance:
Copy file name to clipboardExpand all lines: 1-js/4-object-basics/05-constructor-new/article.md
+33Lines changed: 33 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -85,6 +85,39 @@ let user = new function() {
85
85
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 for a single complex object only.
86
86
````
87
87
88
+
## Dual-use constructors: new.target
89
+
90
+
Inside a function, we can check how it is called with `new` or without it, using a special `new.target` property.
91
+
92
+
It is empty for ordinary runs and equals the function if called with `new`:
93
+
94
+
```js run
95
+
functionUser() {
96
+
alert(new.target);
97
+
}
98
+
99
+
User(); // undefined
100
+
newUser(); // function User { ... }
101
+
```
102
+
103
+
That can be used to allow both `new` and ordinary syntax work the same:
104
+
105
+
106
+
```js run
107
+
functionUser(name) {
108
+
if (!new.target) { // if you run me without new
109
+
returnnewUser(name); // ...I will add new for you
110
+
}
111
+
112
+
this.name= name;
113
+
}
114
+
115
+
let john =User("John"); // redirects call to new User
116
+
alert(john.name); // John
117
+
```
118
+
119
+
This approach is sometimes used in libraries to make the syntax more flexible. Probably not a good thing to use everywhere though, because it makes a bit less obvious what's going on for a person who's familiar with internals of `User`.
120
+
88
121
## Return from constructors
89
122
90
123
Usually, constructors do not have a `return` statement. Their task is to write all necessary stuff into `this`, and it automatically becomes the result.
Copy file name to clipboardExpand all lines: 1-js/4-object-basics/07-object-toprimitive/article.md
+9-9Lines changed: 9 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,15 +16,15 @@ The conversion of an object to primitive value (a number or a string) is a rare
16
16
17
17
Just think about cases when such conversion may be necessary. For instance, numeric conversion happens when we compare an object against a primitive: `user > 18`. But what such comparison actually means? Are we going to compare `18` against user's age? Then it would be more obvious to write `user.age > 18`. And it's easier to read and understand it too.
18
18
19
-
Or, for a string conversion... Where does it happen? Usually, when we output an object. But simple ways of object-as-string output like `alert(user)` are only used for debugging and logging purposes. For real stuff, the output is more complicated, we may need to provide it additional parameters. That's why we usually implement it using object methods like `user.format()` or even in more advanced ways.
19
+
Or, for a string conversion... Where does it happen? Usually, when we output an object. But simple ways of object-as-string output like `alert(user)` are only used for debugging and logging purposes. For real stuff, the output is more complicated, we may need to configure it with additional parameters. That's why it is usually implemented with object methods like `user.format()` or even in more advanced ways.
20
20
21
21
So, most of the time, it's more flexible and gives more readable code to explicitly write an object property or call a method than rely on the conversion.
22
22
23
23
That said, there are still valid reasons why we should know how to-primitive conversion works.
24
24
25
-
- Simple object-as-string output may be useable sometimes. Without a customized conversion it will show `[object Object]`.
25
+
- Simple object-as-string output may be useable sometimes.
26
26
- Many built-in objects implement their own to-primitive conversion, we plan to cover that.
27
-
- Sometimes it just happens (on mistake?), and we should understand what's going on.
27
+
- Sometimes an unexpected conversion happens, and we should understand what's going on.
28
28
- Okay, the final one. There are quizzes and questions on interviews that rely on that knowledge. Looks like people think it's a good sigh that person understands Javascript if he knows type conversions well.
29
29
30
30
## ToPrimitive
@@ -78,7 +78,7 @@ There are 3 types (also called "hints") of object-to-primitive conversion:
78
78
79
79
Please note -- there are only three conversions. That simple. There is no "boolean" (all objects are `true` in boolean context) or anything else. And if we treat `"default"` and `"number"` the same, like most built-ins do, then there are only two conversions.
80
80
81
-
To do the conversion, Javascript tries to find and call these three object methods:
81
+
To do the conversion, Javascript tries to find and call three object methods:
82
82
83
83
1.`Symbol.toPrimitive(hint)` if exists,
84
84
2. Otherwise if hint is `"string"`, try `toString()` and `valueOf()`, whatever exists.
@@ -109,7 +109,7 @@ As we can see from the code, `user` becomes a self-descriptive string or a money
109
109
110
110
### toString/valueOf
111
111
112
-
Methods `toString` and `valueOf` come from the ancient times. That's why they are not symbols. They provide an alternative "old-style" way to implement the conversion.
112
+
Methods `toString` and `valueOf` come from ancient times. That's why they are not symbols. They provide an alternative "old-style" way to implement the conversion.
113
113
114
114
If there's no `Symbol.toPrimitive` then Javascript tries to find them and try in the order:
115
115
@@ -166,20 +166,20 @@ There is no control whether `toString()` returns exactly a string, or whether `S
166
166
167
167
**The only mandatory thing: these methods must return a primitive.**
168
168
169
-
An operation that was the reason for the conversion gets that primitive, and then continues to work with it, applying further conversions if necessary.
169
+
An operation that initiated the conversion gets that primitive, and then continues to work with it, applying further conversions if necessary.
170
170
171
171
For instance:
172
172
173
-
- All mathematical operations except binary plus apply `ToNumber`:
173
+
- All mathematical operations except binary plus apply `ToNumber` after `ToPrimitive` with `"number"` hint:
174
174
175
175
```js run
176
176
let obj = {
177
-
toString() { // toString used for numeric conversion in the absense of valueOf
177
+
toString() { // toString handles all ToPrimitive in the absense of other methods
178
178
return"2";
179
179
}
180
180
};
181
181
182
-
alert(obj *2); // 4
182
+
alert(obj *2); // 4, ToPrimitive gives "2", then it becomes 2
183
183
```
184
184
185
185
- Binary plus first checks if the primitive is a string, and then does concatenation, otherwise performs `ToNumber` and works with numbers.
0 commit comments