◐ Shell
reader mode source ↗
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
File filter
Conversations
Jump to
Diff view
Apply and reload
Show whitespace
Diff view
Apply and reload
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
That's because the child constructor must call `super()`.

Here's the corrected code:

```js run
class Animal {
Expand All @@ -21,7 +21,7 @@ class Rabbit extends Animal {
}

*!*
let rabbit = new Rabbit("White Rabbit"); // ok now
*/!*
alert(rabbit.name); // White Rabbit
```
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
clock.start();


/* Your class should work like this: */

/*

Expand Down
Original file line number Diff line number Diff line change
@@ -2,14 +2,14 @@ importance: 5

---

# Extended clock

We've got a `Clock` class. As of now, it prints the time every second.


[js src="source.view/clock.js"]

Create a new class `ExtendedClock` that inherits from `Clock` and adds the parameter `precision` -- the number of `ms` between "ticks". Should be `1000` (1 second) by default.

- Your code should be in the file `extended-clock.js`
- Don't modify the original `clock.js`. Extend it.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
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;
}
Expand All @@ -19,16 +19,16 @@ 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 {}
Expand All @@ -37,45 +37,45 @@ 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.svg)

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` |
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ 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 {
Expand All @@ -18,17 +18,17 @@ class Rabbit {
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 {
Expand Down
Loading
Toggle all file notes Toggle all file annotations