◐ 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,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 themselves (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
@@ -2,11 +2,11 @@ importance: 3

---

# 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,16 +18,16 @@ class Rabbit {
let rabbit = new Rabbit("Rab");

*!*
// hasOwnProperty method is from 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