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: objects-classes/ch3.md
+166-1Lines changed: 166 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,7 +5,7 @@
5
5
| :--- |
6
6
| Work in progress |
7
7
8
-
The class-design pattern generally entails defining an abstract definition for a *type of thing* (class), including data (members) and behaviors (methods), and then creating one or more concrete *instances* of this class definition as actual objects that can perform tasks. Moreover, class-orientation allows declaring a relationship between two or more classes, through what's called "inheritance", to derive new and augmented "subclasses".
8
+
The class-design pattern generally entails defining a general definition for a *type of thing* (class), including data (members) and behaviors (methods), and then creating one or more concrete *instances* of this class definition as actual objects that can interact and perform tasks. Moreover, class-orientation allows declaring a relationship between two or more classes, through what's called "inheritance", to derive new and augmented "subclasses" that mix-n-match and even re-define behaviors.
9
9
10
10
Prior to ES6 (2015), JS developers mimicked aspects of class-oriented (aka "object-oriented") design using plain functions and objects, along with the `[[Prototype]]` mechanism (as explained in the previous chapter) -- so called "prototypal classes".
11
11
@@ -16,3 +16,168 @@ At the time of ES6's `class` being introduced, this new dedicated syntax was alm
16
16
Even though `class` now bears almost no resemblance to older "prototypal class" code style, the JS engine is still *just* wiring up objects to each other through the existing `[[Prototype]]` mechanism. In other words, `class` is not its own separate pillar of the language (as `[[Prototype]]` is), but more like the fancy, decorative *Capital* that tops the pillar/column.
17
17
18
18
That said, since `class` style code has now replaced virtually all previous "prototypal class" coding style, the main text here focuses only on `class` and its various particulars. For historical purposes, we'll briefly cover the old "prototypal class" style in Appendix A.
19
+
20
+
## The `class` Keyword
21
+
22
+
The `class` keyword defines either a declaration or expression for a class. As a declaration, a class definition appears in a statement position and looks like this:
23
+
24
+
```js
25
+
classSomethingCool {
26
+
// ..
27
+
}
28
+
```
29
+
30
+
As an expression, a class definition appears in a value position and can either have a name or be anonymous:
31
+
32
+
```js
33
+
// named class expression
34
+
constsomething=classSomethingCool {
35
+
// ..
36
+
};
37
+
38
+
// anonymous class expression
39
+
constanother=class {
40
+
// ..
41
+
};
42
+
```
43
+
44
+
The contents of a `class` body typically include one or more method definitions:
45
+
46
+
```js
47
+
classSomethingCool {
48
+
greeting() {
49
+
console.log("Hello!");
50
+
}
51
+
52
+
appreciate() {
53
+
console.log("Thanks!");
54
+
}
55
+
}
56
+
```
57
+
58
+
Inside a `class` body, methods are defined without the `function` keyword, and there's no `,` or `;` separators between the method definitions.
59
+
60
+
### The Constructor
61
+
62
+
One special method that all classes have is called a "constructor". If omitted, there's a default empty constructor assumed in the definition.
63
+
64
+
If defined, this constructor gets invoked any time a `new` instance of the class is created:
65
+
66
+
```js
67
+
classSomethingCool {
68
+
constructor() {
69
+
console.log("Here's your new instance!");
70
+
}
71
+
}
72
+
73
+
var thing =newSomethingCool();
74
+
// Here's your new instance!
75
+
```
76
+
77
+
Even though the syntax implies a function actually named `constructor` exists, JS will not create such a function; instead it defines a function as specified, but with the name of the class (`SomethingCool` above):
78
+
79
+
```js
80
+
typeof SomethingCool; // "function"
81
+
```
82
+
83
+
It's not *just* a function, though; this special kind of function behaves a bit differently:
84
+
85
+
```js
86
+
SomethingCool.toString();
87
+
// class SomethingCool {
88
+
// ..
89
+
// }
90
+
91
+
SomethingCool();
92
+
// TypeError: Class constructor SomethingCool cannot
93
+
// be invoked without 'new'
94
+
95
+
SomethingCool.call({});
96
+
// TypeError: Class constructor SomethingCool cannot
97
+
// be invoked without 'new'
98
+
```
99
+
100
+
You can construct as many different instances of a class as you want:
101
+
102
+
```js
103
+
var one =newSomethingCool();
104
+
var two =newSomethingCool();
105
+
var three =newSomethingCool();
106
+
```
107
+
108
+
Each of `one`, `two`, and `three` here are objects that are independent instances of the `SomethingCool` class.
109
+
110
+
| NOTE: |
111
+
| :--- |
112
+
| Each of the `one`, `two`, and `three` objects have a `[[Prototype]]` linkage to the `SomethingCool.prototype` object. In this code, `SomethingCool` is both a `class` definition and the constructor function of the same name. See Chapter 2 for more details. |
113
+
114
+
If you add a property to the object `one`:
115
+
116
+
```js
117
+
one.value=42;
118
+
```
119
+
120
+
That property now exists only on `one`, and does not exist in any way that the independent `two` or `three` objects can access:
121
+
122
+
```js
123
+
two.value; // undefined
124
+
three.value; // undefined
125
+
```
126
+
127
+
### Class Methods
128
+
129
+
As shown above, a class definition can include one or more method definitions. Each method definition is added to the `prototype` object of the constructor:
130
+
131
+
```js
132
+
classSomethingCool {
133
+
constructor() {
134
+
console.log("Here's your new instance!");
135
+
}
136
+
137
+
greeting() {
138
+
console.log("Hello!");
139
+
}
140
+
}
141
+
142
+
var thing =newSomethingCool();
143
+
144
+
thing.greeting(); // Hello!
145
+
```
146
+
147
+
Just to be clear: the `greeting` property (method) *looks like* it's on (owned by) the `thing` object here. But that's a mirage.
148
+
149
+
Actually, `greeting` only exists at `SomethingCool.prototype.greeting`. But since `thing` is `[[Prototype]]` linked to `SomethingCool.prototype` (see Chapter 2), the `thing.greeting()` reference traverses the `[[Prototype]]` chain and finds the method to execute.
150
+
151
+
Class methods should only be invoked via an instance; `SomethingCool.greeting()` doesn't work because there *is no* such property `SomethingCool.greeting`. You *could* invoke `SomethingCool.prototype.greeting()`, but that's not generally proper/advised in standard class-oriented coding. Always access methods via the instances.
152
+
153
+
## Class Instance `this`
154
+
155
+
We will cover the `this` keyword in much more detail in a subsequent chapter. But as it relates to class-oriented code, the `this` keyword generally refers to the current instance that's the context of any method invocation.
156
+
157
+
In the constructor, as well as any methods, you can use `this.` to either add or access properties on the current instance:
158
+
159
+
```js
160
+
classSomethingCool {
161
+
constructor() {
162
+
// add a property to the current instance
163
+
this.number=42;
164
+
}
165
+
166
+
speak() {
167
+
// access the property from the current instance
168
+
console.log(`My favorite number is ${this.number}!`);
169
+
}
170
+
}
171
+
172
+
var thing =newSomethingCool();
173
+
174
+
thing.number; // 42
175
+
176
+
thing.speak(); // My favorite number is 42!
177
+
```
178
+
179
+
Any properties not holding function values, which are added to a class instance (usually via the constructor), are referred to as *members*, as opposed to the term *methods* for executable functions.
180
+
181
+
While the `thing.speak()` method is running, the `this` reference inside that method is pointing at the same object that `thing` references. That's why both `thing.number` and `this.number` reveal the same `42` value that the constructor set with its `this.number = 42` operation.
0 commit comments