-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
248 additions
and
240 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+25.1 KB
...nheritance/10-class-inheritance/3-class-extend-object/rabbit-extends-object.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+62.6 KB
...ritance/10-class-inheritance/3-class-extend-object/rabbit-extends-object@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 87 additions & 0 deletions
87
1-js/07-object-inheritance/10-class-inheritance/3-class-extend-object/solution.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
The answer has two parts. | ||
|
||
The first, an easy one is that the inheriting class needs to call `super()` in the constructor. Otherwise `"this"` won't be "defined". | ||
|
||
So here's the fix: | ||
|
||
```js run | ||
class Rabbit extends Object { | ||
constructor(name) { | ||
*!* | ||
super(); // need to call the parent constructor when inheriting | ||
*/!* | ||
this.name = name; | ||
} | ||
} | ||
|
||
let rabbit = new Rabbit("Rab"); | ||
|
||
alert( rabbit.hasOwnProperty('name') ); // true | ||
``` | ||
|
||
But that's not all yet. | ||
|
||
Even after the fix, there's still important difference in `"class Rabbit extends Object"` versus `class Rabbit`. | ||
|
||
As we know, the "extends" syntax sets up two prototypes: | ||
|
||
1. Between `"prototype"` of the constructor functions (for methods). | ||
2. Between the constructor functions itself (for static methods). | ||
|
||
In our case, for `class Rabbit extends Object` it means: | ||
|
||
```js run | ||
class Rabbit extends Object {} | ||
|
||
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true | ||
alert( Rabbit.__proto__ === Object ); // (2) true | ||
``` | ||
|
||
So we can access static methods of `Object` via `Rabbit`, like this: | ||
|
||
```js run | ||
class Rabbit extends Object {} | ||
|
||
*!* | ||
// normally we call Object.getOwnPropertyNames | ||
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b | ||
*/!* | ||
``` | ||
|
||
And if we don't use `extends`, then `class Rabbit` does not get the second reference. | ||
|
||
Please compare with it: | ||
|
||
```js run | ||
class Rabbit {} | ||
|
||
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true | ||
alert( Rabbit.__proto__ === Object ); // (2) false (!) | ||
|
||
*!* | ||
// error, no such function in Rabbit | ||
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error | ||
*/!* | ||
``` | ||
|
||
For the simple `class Rabbit`, the `Rabbit` function has the same prototype | ||
|
||
```js run | ||
class Rabbit {} | ||
|
||
// instead of (2) that's correct for Rabbit (just like any function): | ||
alert( Rabbit.__proto__ === Function.prototype ); | ||
``` | ||
|
||
By the way, `Function.prototype` has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`. | ||
|
||
Here's the picture: | ||
|
||
![](rabbit-extends-object.png) | ||
|
||
So, to put it short, there are two differences: | ||
|
||
| class Rabbit | class Rabbit extends Object | | ||
|--------------|------------------------------| | ||
| -- | needs to call `super()` in constructor | | ||
| `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` | |
43 changes: 43 additions & 0 deletions
43
1-js/07-object-inheritance/10-class-inheritance/3-class-extend-object/task.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
importance: 5 | ||
|
||
--- | ||
|
||
# Class extends Object? | ||
|
||
As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods. | ||
|
||
Like demonstrated here: | ||
|
||
```js run | ||
class Rabbit { | ||
constructor(name) { | ||
this.name = name; | ||
} | ||
} | ||
|
||
let rabbit = new Rabbit("Rab"); | ||
|
||
*!* | ||
// hasOwnProperty method is from Object.prototype | ||
// rabbit.__proto__ === Object.prototype | ||
alert( rabbit.hasOwnProperty('name') ); // true | ||
*/!* | ||
``` | ||
|
||
So, is it correct to say that `"class Rabbit extends Object"` does exactly the same as `"class Rabbit"`, or not? | ||
|
||
Will it work? | ||
|
||
```js | ||
class Rabbit extends Object { | ||
constructor(name) { | ||
this.name = name; | ||
} | ||
} | ||
|
||
let rabbit = new Rabbit("Rab"); | ||
|
||
alert( rabbit.hasOwnProperty('name') ); // true | ||
``` | ||
|
||
If it won't please fix the code. |
Oops, something went wrong.