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/ch1.md
+4-2Lines changed: 4 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -96,7 +96,7 @@ In this case, `favoriteNumber` is not holding a numeric value, but rather a func
96
96
97
97
### Looks Like JSON?
98
98
99
-
You may notice that this object-literal syntax resembles "JSON" (JavaScript Object Notation):
99
+
You may notice that this object-literal syntax we've seen thus far resembles a related syntax, "JSON" (JavaScript Object Notation):
100
100
101
101
```json
102
102
{
@@ -106,7 +106,7 @@ You may notice that this object-literal syntax resembles "JSON" (JavaScript Obje
106
106
}
107
107
```
108
108
109
-
The biggest differences between object literals and JSON are:
109
+
The biggest differences between JS's object literals and JSON are, for objects defined as JSON:
110
110
111
111
1. property names must be quoted with `"` double-quote characters
112
112
@@ -123,6 +123,8 @@ myObj = {
123
123
};
124
124
```
125
125
126
+
One other minor difference is, JSON syntax -- that is, text that will be *parsed* as JSON, such as from a `.json` file -- is stricter than general JS. For example, JS allows comments (`// ..` and `/* .. */`), and trailing `,` commas in object and array expressions; JSON does not allow any of these. Thankfully, JSON does still allow arbitrary whitespace.
127
+
126
128
### Property Names
127
129
128
130
Property names in object literals are almost always treated/coeced as string values. One exception to this is for integer (or "integer looking") property "names":
Copy file name to clipboardExpand all lines: objects-classes/ch2.md
+43-15Lines changed: 43 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -274,7 +274,7 @@ We already saw several implications of `[[Prototype]]` linkage in Chapter 1. For
274
274
275
275
| WARNING: |
276
276
| :--- |
277
-
| That `Object.prototype` name itself can be confusing, since it uses a property called `prototype`. How are `[[Prototype]]` and `prototype` related!? Put such questions/confusion on pause for a bit, as we'll come back an explain the differences between `[[Prototype]]` and `prototype`soon. For the moment, just assume the presence of this important but weirdly named built-in object, `Object.prototype`. |
277
+
| That `Object.prototype` name itself can be confusing, since it uses a property called `prototype`. How are `[[Prototype]]` and `prototype` related!? Put such questions/confusion on pause for a bit, as we'll come back an explain the differences between `[[Prototype]]` and `prototype`later in this chapter. For the moment, just assume the presence of this important but weirdly named built-in object, `Object.prototype`. |
We're taking advantage of this internal `[[Prototype]]` linkage, without really realizing it. Since `myObj` does not have `toString` or `hasOwnPropertyName` properties defined on it, those property accesses actually end up **DELEGATING** the access to continue its lookup along the `[[Prototype]]` chain.
297
+
We're taking advantage of this internal `[[Prototype]]` linkage, without really realizing it. Since `myObj` does not have `toString` or `hasOwnProperty` properties defined on it, those property accesses actually end up **DELEGATING** the access to continue its lookup along the `[[Prototype]]` chain.
298
298
299
-
Since `myObj` is `[[Prototype]]`-linked to the object named `Object.prototype`, the lookup for `toString` and `hasOwnPropertyName` properties continues on that object; and indeed, these methods are found there!
299
+
Since `myObj` is `[[Prototype]]`-linked to the object named `Object.prototype`, the lookup for `toString` and `hasOwnProperty` properties continues on that object; and indeed, these methods are found there!
300
300
301
-
The ability for `myObj.toString` to access the `toString` property even though it doesn't actually have it, is commonly referred to as "inheritance", or more specifically, "prototypal inheritance". The `toString` and `hasOwnPropertyName` properties, along with many others, are said to be "inherited properties" on `myObj`.
301
+
The ability for `myObj.toString` to access the `toString` property even though it doesn't actually have it, is commonly referred to as "inheritance", or more specifically, "prototypal inheritance". The `toString` and `hasOwnProperty` properties, along with many others, are said to be "inherited properties" on `myObj`.
302
302
303
303
| NOTE: |
304
304
| :--- |
305
305
| I have a lot of frustrations with the usage of the word "inheritance" here -- it should be called "delegation"! -- but that's what most people refer to it as, so we'll begrudgingly comply and use that same terminology for now (albeit under protest, with " quotes). I'll save my objections for an appendix of this book. |
306
306
307
-
`Object.prototype` has several built-in properties and methods, all of which are "inherited" by any object that is `[[Prototype]]`-linked, either directly or through another object's linkage, to `Object.prototype`.
307
+
`Object.prototype` has several built-in properties and methods, all of which are "inherited" by any object that is `[[Prototype]]`-linked, either directly or indirectly through another object's linkage, to `Object.prototype`.
308
308
309
309
Some common "inherited" properties from `Object.prototype` include:
310
310
@@ -315,6 +315,32 @@ Some common "inherited" properties from `Object.prototype` include:
315
315
*`hasOwnProperty(..)`
316
316
*`isPrototypeOf(..)`
317
317
318
+
Recall `hasOwnProperty(..)`, which we saw earlier gives us a boolean check for whether a certain property (by string name) is owned by an object:
319
+
320
+
```js
321
+
myObj = {
322
+
favoriteNumber:42
323
+
};
324
+
325
+
myObj.hasOwnProperty("favoriteNumber"); // true
326
+
```
327
+
328
+
It's always been considered somewhat unfortunate (semantic organization, naming conflicts, etc) that such an important utility as `hasOwnProperty(..)` was included on the Object `[[Prototype]]` chain as an instance method, instead of being defined as a static utility.
329
+
330
+
As of ES2022, JS has finally added the static version of this utility: `Object.hasOwn(..)`.
331
+
332
+
```js
333
+
myObj = {
334
+
favoriteNumber:42
335
+
};
336
+
337
+
Object.hasOwn(myObj,"favoriteNumber"); // true
338
+
```
339
+
340
+
This form is now considered the more preferable and robust option, and the instance method (`hasOwnProperty(..)`) form should now generally be avoided.
341
+
342
+
Somewhat unfortunately and inconsisently, there's not (yet, as of time of writing) corresponding static utilities, like `Object.isPrototype(..)` (instead of the instance method `isPrototypeOf(..)`). But at least `Object.hasOwn(..)` exists, so that's progress.
343
+
318
344
### Creating An Object With A Different `[[Prototype]]`
319
345
320
346
By default, any object you create in your programs will be `[[Prototype]]`-linked to that `Object.prototype` object. However, you can create an object with a different linkage like this:
@@ -335,15 +361,17 @@ Alternately, but less preferably, you can use the `{ .. }` literal syntax along
335
361
336
362
```js
337
363
myObj = {
338
-
__proto__: differentObj
364
+
__proto__: differentObj,
365
+
366
+
// .. the rest of the object definition
339
367
};
340
368
```
341
369
342
370
| WARNING: |
343
371
| :--- |
344
-
| The strange looking `__proto__` property existed in some JS engines for more than 20 years, but was only standardized in JS as of ES6. Even still, it was added in Appendix B of the specification[^specApB], which lists features that TC39 begrudgingly includes because they exist popularly in various browser-based JS engines and therefore are a de-facto reality even if they didn't originate with TC39. This feature is thus "guaranteed" by the spec to exist in all conforming browser-based JS engines, but is not necessarily guaranteed to work in other independent JS engines. Node.js uses the JS engine (v8) from the Chrome browser, so Node.js gets `__proto__` by default/accident. Be careful when using `__proto__` to be aware of all the JS engine environments your code will run in. |
372
+
| The strange looking `__proto__` property has been in some JS engines for more than 20 years, but was only standardized in JS as of ES6 (in 2015). Even still, it was added in Appendix B of the specification[^specApB], which lists features that TC39 begrudgingly includes because they exist popularly in various browser-based JS engines and therefore are a de-facto reality even if they didn't originate with TC39. This feature is thus "guaranteed" by the spec to exist in all conforming browser-based JS engines, but is not necessarily guaranteed to work in other independent JS engines. Node.js uses the JS engine (v8) from the Chrome browser, so Node.js gets `__proto__` by default/accident. Be careful when using `__proto__` to be aware of all the JS engine environments your code will run in. |
345
373
346
-
Whether you use `Object.create(..)` or `__proto__`, the object in question will be `[[Prototype]]`-linked to a different object than the default `Object.prototype`.
374
+
Whether you use `Object.create(..)` or `__proto__`, the created object in question will usually be `[[Prototype]]`-linked to a different object than the default `Object.prototype`.
347
375
348
376
#### Empty `[[Prototype]]` Linkage
349
377
@@ -355,7 +383,7 @@ However, you can also define objects with their own `null` value for `[[Prototyp
355
383
emptyObj =Object.create(null);
356
384
// or: emptyObj = { __proto__: null }
357
385
358
-
empty.toString; // undefined
386
+
emptyObj.toString; // undefined
359
387
```
360
388
361
389
It can be quite useful to create an object with no `[[Prototype]]` linkage to `Object.prototype`. For example, as mentioned in Chapter 1, the `in` and `for..in` constructs will consult the `[[Prototype]]` chain for inherited properties. But this may be undesirable, as you may not want something like `"toString" in myObj` to resolve successfully.
@@ -366,11 +394,11 @@ Moreover, an object with an empty `[[Prototype]]` is safe from any accidental "i
366
394
367
395
Notice that public property name `prototype` in the name/location of this special object, `Object.prototype`? What's that all about?
368
396
369
-
`Object` is the `Object(..)` function; by default, all functions (which are objects!) have such a `prototype` property on them, pointing at an object.
397
+
`Object` is the `Object(..)` function; by default, all functions (which are themselves objects!) have such a `prototype` property on them, pointing at an object.
370
398
371
399
Any here's where the name conflict between `[[Prototype]]` and `prototype` really bites us. The `prototype` property on a function doesn't define any linkage that the function itself experiences. Indeed, functions (as objects) have their own internal `[[Prototype]]` linkage somewhere else -- more on that in a second.
372
400
373
-
Rather, the `prototype` property on a function refers to an object that should be *linked to* by any other object that is created when calling that function with the `new` keyword:
401
+
Rather, the `prototype` property on a function refers to an object that should be *linked TO* by any other object that is created when calling that function with the `new` keyword:
374
402
375
403
```js
376
404
myObj = {};
@@ -379,15 +407,15 @@ myObj = {};
379
407
myObj =newObject();
380
408
```
381
409
382
-
Since the `{ .. }` object literal syntax is essentially the same as a `new Object()` call, the built-in object named/located at `Object.prototype` is used as the internal `[[Prototype]]`linkage for the new object we create and name `myObj`.
410
+
Since the `{ .. }` object literal syntax is essentially the same as a `new Object()` call, the built-in object named/located at `Object.prototype` is used as the internal `[[Prototype]]`value for the new object we create and name `myObj`.
383
411
384
412
Phew! Talk about a topic made significantly more confusing just because of the name overlap between `[[Prototype]]` and `prototype`!
385
413
386
414
----
387
415
388
-
But where do functions themselves (as objects!) link to, `[[Prototype]]` wise? They link to `Function.prototype`, yet another built-in object, located at the `prototype` property on the `Function` function.
416
+
But where do functions themselves (as objects!) link to, `[[Prototype]]` wise? They link to `Function.prototype`, yet another built-in object, located at the `prototype` property on the `Function(..)` function.
389
417
390
-
In other words, you could think of functions themselves as having been "created" by a `new Function(..)` call, and then `[[Prototype]]`-linked to the `Function.prototype` object. This object contains properties/methods all functions "inherit" by default, such as `toString()` (to serialize the source code of a function) and `call(..)` / `apply(..)` / `bind(..)` (we'll explain these later in this book).
418
+
In other words, you can think of functions themselves as having been "created" by a `new Function(..)` call, and then `[[Prototype]]`-linked to the `Function.prototype` object. This object contains properties/methods all functions "inherit" by default, such as `toString()` (to string serialize the source code of a function) and `call(..)` / `apply(..)` / `bind(..)` (we'll explain these later in this book).
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".
9
+
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
+
12
+
But to many developers joy and relief, ES6 introduced dedicated syntax, including the `class` and `extends` keywords, to express class-oriented design more declaratively.
13
+
14
+
At the time of ES6's `class` being introduced, this new dedicated syntax was almost entirely *just syntactic sugar* to make class definitions more convenient and readable. However, in the many years since ES6, `class` has matured and grown into its own first class feature mechanism, accruing a significant amount of dedicated syntax and complex behaviors that far surpass the pre-ES6 "prototypal class" capabilities.
15
+
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
+
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.
0 commit comments