Buscar..
Prototipo de función estándar
Comience por definir una función Foo
que usaremos como constructor.
function Foo (){}
Al editar Foo.prototype
, podemos definir propiedades y métodos que serán compartidos por todas las instancias de Foo
.
Foo.prototype.bar = function() {
return 'I am bar';
};
Luego podemos crear una instancia usando la new
palabra clave y llamar al método.
var foo = new Foo();
console.log(foo.bar()); // logs `I am bar`
Diferencia entre Object.key y Object.prototype.key
A diferencia de lenguajes como Python, las propiedades estáticas de la función constructora no se heredan a las instancias. Las instancias solo se heredan de su prototipo, que se hereda del prototipo del tipo principal. Las propiedades estáticas nunca se heredan.
function Foo() {};
Foo.style = 'bold';
var foo = new Foo();
console.log(Foo.style); // 'bold'
console.log(foo.style); // undefined
Foo.prototype.style = 'italic';
console.log(Foo.style); // 'bold'
console.log(foo.style); // 'italic'
Nuevo objeto del prototipo.
En JavaScript, cualquier objeto puede ser el prototipo de otro. Cuando un objeto se crea como un prototipo de otro, heredará todas las propiedades de su padre.
var proto = { foo: "foo", bar: () => this.foo };
var obj = Object.create(proto);
console.log(obj.foo);
console.log(obj.bar());
Salida de consola:
> "foo"
> "foo"
NOTA Object.create
está disponible en ECMAScript 5, pero aquí hay un polyfill si necesita soporte para ECMAScript 3
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
Object.create ()
El método Object.create () crea un nuevo objeto con el objeto prototipo y las propiedades especificados.
Sintaxis: Object.create(proto[, propertiesObject])
Parámetros :
- proto (El objeto que debería ser el prototipo del objeto recién creado).
- propertiesObject (Opcional. Si se especifica y no está indefinido, un objeto cuyas enumerables propiedades propias (es decir, aquellas propiedades definidas en sí mismo y no enumerables propiedades a lo largo de su cadena de prototipos) especifica los descriptores de propiedades que se agregarán al objeto recién creado, con el correspondiente nombres de propiedades. Estas propiedades corresponden al segundo argumento de Object.defineProperties ().)
Valor de retorno
Un nuevo objeto con el objeto prototipo especificado y las propiedades.
Excepciones
Una excepción TypeError si el parámetro proto no es nulo o un objeto.
Herencia prototípica
Supongamos que tenemos un objeto plano llamado prototype
:
var prototype = { foo: 'foo', bar: function () { return this.foo; } };
Ahora queremos otro objeto llamado obj
que herede del prototype
, que es lo mismo que decir que prototype
es el prototipo de obj
var obj = Object.create(prototype);
Ahora todas las propiedades y métodos del prototype
estarán disponibles para obj
console.log(obj.foo);
console.log(obj.bar());
Salida de consola
"foo"
"foo"
La herencia prototípica se realiza a través de referencias de objetos internamente y los objetos son completamente mutables. Esto significa que cualquier cambio que realice en un prototipo afectará inmediatamente a todos los demás objetos de los que el prototipo sea prototipo.
prototype.foo = "bar";
console.log(obj.foo);
Salida de consola
"bar"
Object.prototype
es el prototipo de cada objeto, por lo que se recomienda encarecidamente que no te metas con él, especialmente si utilizas una biblioteca de terceros, pero podemos jugar con él un poco.
Object.prototype.breakingLibraries = 'foo';
console.log(obj.breakingLibraries);
console.log(prototype.breakingLibraries);
Salida de consola
"foo"
"foo"
Dato curioso , he usado la consola del navegador para hacer estos ejemplos y he roto esta página agregando la propiedad breakingLibraries
.
Herencia pseudo-clásica
Es una emulación de la herencia clásica utilizando la herencia prototípica que muestra qué tan poderosos son los prototipos. Fue hecho para hacer que el lenguaje sea más atractivo para los programadores que vienen de otros idiomas.
NOTA IMPORTANTE : desde ES6 no tiene sentido usar herencia pseudocálica ya que el lenguaje simula clases convencionales . Si no estás usando ES6, deberías . Si aún desea utilizar el patrón de herencia clásico y está en un entorno ECMAScript 5 o inferior, entonces su mejor apuesta es pseudo-clásica.
Una "clase" es solo una función que está diseñada para ser llamada con el new
operando y se usa como un constructor.
function Foo(id, name) {
this.id = id;
this.name = name;
}
var foo = new Foo(1, 'foo');
console.log(foo.id);
Salida de consola
1
foo es una instancia de Foo. La convención de codificación de JavaScript dice que si una función comienza con mayúsculas y minúsculas, se puede llamar como un constructor (con el new
operando).
Para agregar propiedades o métodos a la "clase", debe agregarlos a su prototipo, que se puede encontrar en la propiedad prototype
del constructor.
Foo.prototype.bar = 'bar';
console.log(foo.bar);
Salida de consola
bar
De hecho, lo que Foo está haciendo como "constructor" es simplemente crear objetos con Foo.prototype
como su prototipo.
Puedes encontrar una referencia a su constructor en cada objeto.
console.log(foo.constructor);
función Foo (id, nombre) {...
console.log({ }.constructor);
Función Objeto () {[código nativo]}
Y también verifique si un objeto es una instancia de una clase dada con el operador instanceof
console.log(foo instanceof Foo);
cierto
console.log(foo instaceof Object);
cierto
Configurando el prototipo de un objeto
Con ES5 +, la función Object.create
se puede usar para crear un objeto con cualquier otro objeto como prototipo.
const anyObj = {
hello() {
console.log(`this.foo is ${this.foo}`);
},
};
let objWithProto = Object.create(anyObj);
objWithProto.foo = 'bar';
objWithProto.hello(); // "this.foo is bar"
Para crear explícitamente un Objeto sin un prototipo, use null
como el prototipo. Esto significa que el Objeto tampoco se heredará del Object.prototype
y es útil para los Objetos utilizados para los diccionarios de verificación de existencia, por ejemplo
let objInheritingObject = {};
let objInheritingNull = Object.create(null);
'toString' in objInheritingObject; // true
'toString' in objInheritingNull ; // false
Desde ES6, el prototipo de un objeto existente se puede cambiar utilizando Object.setPrototypeOf
, por ejemplo
let obj = Object.create({foo: 'foo'});
obj = Object.setPrototypeOf(obj, {bar: 'bar'});
obj.foo; // undefined
obj.bar; // "bar"
Esto se puede hacer en casi cualquier lugar, incluso en this
objeto o en un constructor.
Nota: este proceso es muy lento en los navegadores actuales y se debe usar con moderación; en su lugar, intente crear el Objeto con el prototipo deseado.
Antes de ES5, la única forma de crear un Objeto con un prototipo definido manualmente era construirlo con new
, por ejemplo
var proto = {fizz: 'buzz'};
function ConstructMyObj() {}
ConstructMyObj.prototype = proto;
var objWithProto = new ConstructMyObj();
objWithProto.fizz; // "buzz"
Este comportamiento es lo suficientemente cercano a Object.create
que es posible escribir un polyfill.