¿La clase extiende el objeto?
Como sabemos, todos los objetos normalmente heredan de Object.prototype y obtienen acceso a métodos de objeto âgenéricosâ como hasOwnProperty etc.
Por ejemplo:
class Rabbit {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
// el método hasOwnProperty proviene de Object.prototype
alert( rabbit.hasOwnProperty('name') ); // verdadero
Pero si lo escribimos explÃcitamente como "class Rabbit extends Object", entonces ¿el resultado serÃa diferente de una simple "class Rabbit"?
¿Cuál es la diferencia?
Aquà un ejemplo de dicho código (no funciona â ¿por qué? ¿Arréglalo?):
class Rabbit extends Object {
constructor(name) {
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // Error
Primero, veamos por qué el código anterior no funciona.
La razón se vuelve evidente si intentamos ejecutarlo. Un constructor de clase heredado tiene que llamar a super(). De lo contrario "this" no será âdefinidoâ.
Asà que aquà está la solución:
class Rabbit extends Object {
constructor(name) {
super(); // necesita llamar al constructor padre cuando se hereda
this.name = name;
}
}
let rabbit = new Rabbit("Rab");
alert( rabbit.hasOwnProperty('name') ); // verdadero
Pero eso no es todo.
Incluso después de arreglarlo, aún existe una diferencia importante entre "class Rabbit extends Object" y class Rabbit.
Como sabemos, la sintaxis âextendsâ configura dos prototipos:
- Entre
"prototype"de las funciones del constructor (para métodos). - Entre las propias funciones del constructor (para métodos estáticos).
En el caso de class Rabbit extends Object significa:
class Rabbit extends Object {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) verdadero
alert( Rabbit.__proto__ === Object ); // (2) verdadero
Entonces Rabbit ahora proporciona acceso a los métodos estáticos de Object a través de Rabbit, asÃ:
class Rabbit extends Object {}
// normalmente llamamos a Object.getOwnPropertyNames
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b
Pero si no tenemos extends Object, entonces Rabbit.__proto__ no está definido como Object.
Aquà está la demostración:
class Rabbit {}
alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) verdadero
alert( Rabbit.__proto__ === Object ); // (2) falso (!)
alert( Rabbit.__proto__ === Function.prototype ); // como cualquier función por defecto
// error, no existe esta función en Rabbit
alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error
Entonces Rabbit no proporciona acceso a métodos estáticos de Object en este caso.
Por cierto, Function.prototype también tiene métodos de función âgenéricosâ, como call, bind etc. Finalmente, están disponibles en ambos casos, por el Object que tiene el constructor incorporado Object.__proto__ === Function.prototype.
Aquà está la imagen:
Por lo tanto, en pocas palabras, existen dos diferencias:
| class Rabbit | class Rabbit extends Object |
|---|---|
| â | necesita llamar a super() en el constructor |
Rabbit.__proto__ === Function.prototype |
Rabbit.__proto__ === Object |