Skip to content

Commit 06f01de

Browse files
committed
add notes about object
1 parent 180d108 commit 06f01de

File tree

5 files changed

+252
-0
lines changed

5 files changed

+252
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# object-toprimitive
2+
3+
[ref object to primitive](https://javascript.info/object-toprimitive)
4+
5+
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).
6+
7+
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.
8+
9+
That’s an important limitation, as the result of obj1 + obj2 can’t be another object!
10+
11+
## Conversion rules
12+
13+
1. All objects are `true` in a boolean context. There are only numeric and string conversions.
14+
2. The numeric conversion happens when we apply mathematical functions on objects
15+
16+
We can fine-tune string and numeric conversion, using special object methods. There are three variants of type conversion, that happen in various situations. They’re called “hints”.
17+
18+
1. "string"
19+
2. "number"
20+
3. "default"
21+
22+
There are three methods to convert object to primitive
23+
24+
**The only mandatory thing: these methods must return a primitive, not an object.**
25+
26+
1. `Symbol.toPrimitive`
27+
2. `toString`
28+
3. `valueOf`
29+
30+
If the method `Symbol.toPrimitive` exists, it’s used for all hints, and no more methods are needed.
31+
32+
```javascript
33+
let user = {
34+
name: 'John',
35+
money: 1000,
36+
37+
[Symbol.toPrimitive](hint) {
38+
alert(`hint: ${hint}`);
39+
return hint == 'string' ? `{name: "${this.name}"}` : this.money;
40+
},
41+
};
42+
43+
// conversions demo:
44+
alert(user); // hint: string -> {name: "John"}
45+
alert(+user); // hint: number -> 1000
46+
alert(user + 500); // hint: default -> 1500
47+
```
48+
49+
If there’s no `Symbol.toPrimitive` then JavaScript tries to find methods `toString` and `valueOf`:
50+
51+
1. For the “string” hint: `toString`, and if it doesn’t exist, then `valueOf` (so `toString` has the priority **for string conversions**).
52+
2. For other hints: `valueOf`, and if it doesn’t exist, then `toString` (so `valueOf` has the priority **for maths**).
53+
54+
The valueOf method returns the object itself.
55+
56+
```javascript
57+
let user = { name: 'John' };
58+
59+
alert(user); // [object Object]
60+
alert(user.valueOf() === user); // true
61+
```
62+
63+
If there’s no `Symbol.toPrimitive` then JavaScript tries to find methods `toString` and `valueOf`:
64+
65+
```javascript
66+
let user = {
67+
name: 'John',
68+
money: 1000,
69+
70+
// for hint="string"
71+
toString() {
72+
return `{name: "${this.name}"}`;
73+
},
74+
75+
// for hint="number" or "default"
76+
valueOf() {
77+
return this.money;
78+
},
79+
};
80+
81+
alert(user); // toString -> {name: "John"}
82+
alert(+user); // valueOf -> 1000
83+
alert(user + 500); // valueOf -> 1500
84+
```
85+
86+
![conversion alog](../images/conversion%20algo.jpg)
87+
88+
```javascript
89+
let user = {
90+
name: 'John',
91+
92+
toString() {
93+
return this.name;
94+
},
95+
};
96+
97+
alert(user); // toString -> John
98+
alert(user + 500); // toString -> John500
99+
```
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Object references and copying
2+
3+
[ref](https://javascript.info/object-copy)
4+
5+
One of the fundamental differences of objects versus primitives is that objects are stored and copied “by reference”, whereas primitive values: strings, numbers, booleans, etc – are always copied “as a whole value”.
6+
7+
![primitive copy](../images/object%20copy.jpg)
8+
9+
**But, copying an object variable creates one more reference to the same object.**
10+
11+
![object copy](../images/object%20copy.jpg)
12+
13+
# Comparison by reference
14+
15+
Two objects are equal only if they are the same object.
16+
17+
For instance, here a and b reference the same object, thus they are equal:
18+
19+
```javascript
20+
let a = {};
21+
let b = a; // copy the reference
22+
23+
alert(a == b); // true, both variables reference the same object
24+
alert(a === b); // true
25+
```
26+
27+
And here two independent objects are not equal, even though they look alike (both are empty):
28+
29+
```javascript
30+
let a = {};
31+
let b = {}; // two independent objects
32+
33+
alert(a == b); // false
34+
```
35+
36+
For comparisons like obj1 > obj2 or for a comparison against a primitive obj == 5, objects are converted to primitives.
37+
38+
# Cloning and merging, Object.assign
39+
40+
If we need to duplicate an object? Create an independent copy, a clone?
41+
42+
we can use following methods for that.
43+
44+
1. spread syntax
45+
2. Object.assign
46+
47+
## 1. spread syntax
48+
49+
```javascript
50+
let obj = { a: 1, b: 2, c: 3 };
51+
52+
// spread the object into a list of parameters
53+
// then return the result in a new object
54+
55+
let objCopy = { ...obj };
56+
```
57+
58+
## 2. Object.assign
59+
60+
The syntax is:
61+
62+
```javascript
63+
Object.assign(dest, [src1, src2, src3...])
64+
```
65+
66+
here's how we can use it to merge several objects into one
67+
68+
```javascript
69+
let user = { name: 'John' };
70+
71+
let permissions1 = { canView: true };
72+
let permissions2 = { canEdit: true };
73+
74+
// copies all properties from permissions1 and permissions2 into user
75+
Object.assign(user, permissions1, permissions2);
76+
77+
// now user = { name: "John", canView: true, canEdit: true }
78+
```
79+
80+
If the copied property name already exists, it gets overwritten:
81+
82+
```javascript
83+
let user = { name: 'John' };
84+
85+
Object.assign(user, { name: 'Pete' });
86+
87+
alert(user.name); // now user = { name: "Pete" }
88+
```
89+
90+
following copies all properties of user into the empty object and returns it.
91+
92+
```javascript
93+
let user = {
94+
name: 'John',
95+
age: 30,
96+
};
97+
98+
let clone = Object.assign({}, user);
99+
```
100+
101+
# Nested cloning
102+
103+
Until now we assumed that all properties of user are primitive. But properties can be references to other objects. How they will be copied?
104+
105+
**Answer: They will be copied by reference.**
106+
107+
```javascript
108+
let user = {
109+
name: 'John',
110+
sizes: {
111+
height: 182,
112+
width: 50,
113+
},
114+
};
115+
116+
let clone = Object.assign({}, user);
117+
118+
alert(user === clone); // FALSE, DIFFERENT OBJECT *****NOTE****
119+
120+
alert(user.sizes === clone.sizes); // true, same object
121+
122+
// user and clone share sizes
123+
user.sizes.width++; // change a property from one place
124+
alert(clone.sizes.width); // 51, see the result from the other one
125+
```
126+
127+
**How to resolve?**
128+
129+
To fix that, we should use a cloning loop that examines each value of `user[key]` and, if it’s an `object`, then replicate its structure as well. That is called a “deep cloning”.
130+
131+
We can use recursion to implement it. Or, to not reinvent the wheel, take an existing implementation, for instance `_.cloneDeep(obj)` from the JavaScript library `lodash`.
132+
133+
# Side effect of storing objects as references
134+
135+
An important side effect of storing objects as references is that an object declared as `const` can be modified.
136+
137+
```javascript
138+
const user = {
139+
name: 'John',
140+
};
141+
142+
user.name = 'Pete'; // (*)
143+
144+
alert(user.name); // Pete
145+
```
146+
147+
The value of `user` is constant, it must always reference the same object, but properties of that object are free to change.
148+
149+
In other words, the const user gives an error only if we try to set `user=...` as a whole.
150+
151+
// TODO [take notes from here - property-descriptors](https://javascript.info/property-descriptors)
152+
153+
That said, if we really need to make constant object properties, it’s also possible, but using totally different methods. We’ll mention that in the chapter Property flags and descriptors.
129 KB
Loading

session 2/images/object copy.jpg

106 KB
Loading
37.8 KB
Loading

0 commit comments

Comments
 (0)