¿Esto quiere decir que los datos heredan propiedades y métodos?
Primero, tienes que olvidarte por un momento de la POO clásica; me refiero por clásica a la POO que implementan lenguajes como C#, Java o PHP. Segundo, debes saber que hay más modelos de POO, uno de ellos, es el modelo prototipado y es el que implementa JavaScript.
Prototipo
¿Qué es un prototipo? Imagina que tienes una fábrica de automóviles, la cual fabrica distintos familias de modelos. Cada familia, tiene un modelo del cual derivan todos, este, es el prototipo de dicha familia.
Un prototipo es simplemente un objeto especial que describe el comportamiento de algo y que sirve como base para la creación de unos nuevos. En JavaScript, todo objeto tiene un prototipo y hereda uno de la función de primer nivel, Object
(Object.prototype
), la cual es la madre de todo tipo de dato en JavaScript:
const emptyObject = {};
console.info(Object.getPrototypeOf(emptyObject));
// o mediante __proto__
console.info(emptyObject.__proto__);
// Algunos métodos que se hereda de Object.prototype
// toString
// toLocaleSting
// hasOwnProperty
// Ver más en: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
console.info(emptyObject.toString);
console.info(emptyObject.toLocaleString);
console.info(emptyObject.hasOwnProperty);
En el código anterior nos damos cuenta que todo objeto, hereda, implícitamente las propiedades y métodos de Object.prototype
. Si vienes de Java, esto aplica igual, ya que en Java, todo objeto hereda de Object
. El siguiente ejempo refuerza lo anterior, utilizando el primitivo de Number
:
const money = 123.50;
console.info(money.toString);
console.info(money.toLocaleString);
console.info(money.hasOwnProperty);
¿Existen metodos heredables y metodos generales?
No solo métodos, si no también propiedades como ya vimos en el apartado anterior. Pero además de heredar propiedades y métodos de Object.prototype
, un objeto también puede tener métodos propios como es obvio.
¿Cómo darse cuenta si un método es propio o heredado? La respuesta es simple: buscando como propiedad en el objeto mismo o en su prototipo:
// false porque toString pertenece a Object.prototype
console.info(String.hasOwnProperty('toString'));
// false porque freeze está en el prototipo de Object
console.info(String.prototype.hasOwnProperty('freeze'));
// true porque fromCharCode sí es propio de String
console.info(String.hasOwnProperty('fromCharCode'));
// false porque endsWith no es una propiedad directa, si no que está en el prototipo de String
console.info(String.hasOwnProperty('endsWith'));
// true porque sí está en su prototipo
console.info(String.prototype.hasOwnProperty('endsWith'));
Un caso curioso es, por ejemplo, que si miras si un primitivo tiene el método de su tipo de dato, te dirá que no lo tiene pero sin embargo, lo puede usar:
const jsRocks = 'claro!';
// false
console.log(jsRocks.hasOwnProperty('codePointAt'));
// 97
console.log(jsRocks.codePointAt(2));
Esto sucede porque implícitamente, cuando se llama a un método sobre un objeto/dato, JavaScript buscará el método dentro del objeto (como propiedad directa), y seguirá buscando en la cadena de prototipos. Si lo encuentra lo ejecuta, si no, verás el clásico error "xxx.yyy is not a function".