Skip to content

Commit

Permalink
up
Browse files Browse the repository at this point in the history
  • Loading branch information
iliakan committed Jan 18, 2017
1 parent 6c9c221 commit a7c00e1
Show file tree
Hide file tree
Showing 14 changed files with 248 additions and 240 deletions.
4 changes: 3 additions & 1 deletion 1-js/03-code-quality/02-coding-style/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,6 @@ Also you can see [the manual](http://eslint.org/docs/user-guide/getting-started)

All syntax rules from this chapter and the style guides aim to increase readability.

When you read style guides and think about "how to write better", the sole criterion is "does the code become more readable and easier to understand?" Then it becomes easier to pick up the best practices for that. Or even abandon some in cases when you see that they don't help.
All of them are debatable.

When we think about "how to write better?", the sole criterion is "what makes the code more readable and easier to understand? what helps to evade errors?" The answer helps to pick up best practices. And maybe to abandon some in case if they don't contribute.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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` |
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.
Loading

0 comments on commit a7c00e1

Please sign in to comment.