refactor classes, add private, minor fixes

This commit is contained in:
Ilya Kantor 2019-03-05 18:44:28 +03:00
parent a0c07342ad
commit 1373f6158c
270 changed files with 1513 additions and 890 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View file

@ -0,0 +1,81 @@
First, let's see why the latter code doesn't work.
The reason becomes obvious if we try to run it. An inheriting class constructor must call `super()`. 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 `Rabbit` now provides access to 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
*/!*
```
But if we don't have `extends Object`, then `Rabbit.__proto__` is not set to `Object`.
Here's the demo:
```js run
class Rabbit {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true
alert( Rabbit.__proto__ === Object ); // (2) false (!)
alert( Rabbit.__proto__ === Function.prototype ); // as any function by default
*!*
// error, no such function in Rabbit
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error
*/!*
```
So `Rabbit` doesn't provide access to static methods of `Object` in that case.
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` |

View file

@ -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 `hasOwnProperty` etc.
For instance:
```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
*/!*
```
But if we spell it out explicitly like `"class Rabbit extends Object"`, then the result would be different from a simple `"class Rabbit"`?
What's the difference?
Here's an example of such code (it doesn't work -- why? fix it?):
```js
class Rabbit extends Object {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // true
```