You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/07-object-oriented-programming/10-class-inheritance/article.md
+11-9Lines changed: 11 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -301,7 +301,7 @@ At the line `(*)` we take `eat` from the prototype (`animal`) and call it in the
301
301
302
302
And in the code above it actually works as intended: we have the correct `alert`.
303
303
304
-
Now let's add one more object to the chain. And we'll see how things break:
304
+
Now let's add one more object to the chain. We'll see how things break:
305
305
306
306
```js run
307
307
let animal = {
@@ -336,20 +336,22 @@ The code doesn't work any more! We can see the error trying to call `longEar.eat
336
336
337
337
It may be not that obvious, but if we trace `longEar.eat()` call, then we can see why. In both lines `(*)` and `(**)` the value of `this` is the current object (`longEar`). That's essential: all object methods get the current object as `this`, not a prototype or something.
338
338
339
-
So, in both lines `(*)` and `(**)` the value of `this.__proto__` is exactly the same: `rabbit`. They both call `rabbit.eat` without going up the chain.
339
+
So, in both lines `(*)` and `(**)` the value of `this.__proto__` is exactly the same: `rabbit`. They both call `rabbit.eat` without going up the chain in the endless loop.
340
340
341
-
In other words:
341
+
Here's the picture of what happens:
342
342
343
-
1. Inside `longEar.eat()`, we pass the call up to `rabbit.eat` giving it the same `this=longEar`.
343
+

344
+
345
+
1. Inside `longEar.eat()`, the line `(**)` calls `rabbit.eat` providing it with `this=longEar`.
344
346
```js
345
347
// inside longEar.eat() we have this = longEar
346
348
this.__proto__.eat.call(this) // (**)
347
349
// becomes
348
350
longEar.__proto__.eat.call(this)
349
-
//or
351
+
//that is
350
352
rabbit.eat.call(this);
351
353
```
352
-
2.Inside `rabbit.eat`, we want to pass the call even higher in the chain, but `this=longEar`, so `this.__proto__.eat` is `rabbit.eat`!
354
+
2.Then in the line `(*)`of`rabbit.eat`, we'd like to pass the call even higher in the chain, but `this=longEar`, so `this.__proto__.eat` is again `rabbit.eat`!
353
355
354
356
```js
355
357
// inside rabbit.eat() we also have this = longEar
@@ -362,9 +364,7 @@ In other words:
362
364
363
365
3. ...So `rabbit.eat` calls itself in the endless loop, because it can't ascend any further.
364
366
365
-

366
-
367
-
There problem is unsolvable, because `this` must always be the calling object itself, no matter which parent method is called. So its prototype will always be the immediate parent of the object. We can't go up the chain.
367
+
The problem can't be solved by using `this` alone.
This way `Rabbit` has access to all static methods of `Animal`.
503
503
504
+
### No static inheritance in built-ins
505
+
504
506
Please note that built-in classes don't have such static `[[Prototype]]` reference. For instance, `Object` has `Object.defineProperty`, `Object.keys` and so on, but `Array`, `Date` etc do not inherit them.
505
507
506
508
Here's the picture structure for `Date` and `Object`:
0 commit comments