Definiendo un prototipo de Javascript

Resuelto Richard Keller asked hace 11 años • 5 respuestas

¿Cuáles son las diferencias funcionales entre los dos prototipos de Javascript siguientes? ¿Existe algún beneficio al elegir uno sobre el otro?

Opción 1:

Person.prototype.sayName = function(name) {
   alert(name);
}

Opcion 2:

Person.prototype = {
   sayName: function(name) {
      alert(name);
   }
}

¿Estoy en lo cierto al suponer que la Opción 2 da como resultado la eliminación de ciertas funciones que están implícitamente vinculadas al prototipo?

Richard Keller avatar Jul 04 '13 22:07 Richard Keller
Aceptado

¿Estoy en lo cierto al suponer que la Opción 2 da como resultado la eliminación de ciertas funciones que están implícitamente vinculadas al prototipo?

Sí exactamente. Aunque la única propiedad implícitamente vinculada es la constructorpropiedad, que rara vez se necesita.

¿Cuáles son las diferencias funcionales?

La opción 1 es simplemente ampliar el prototipo existente. Si ya hay instancias que heredan del objeto prototipo, también Personpodrán utilizar el método. sayNameCon la opción 2, el nuevo prototipo solo se usará para objetos de los que se creen instancias después de la sobrescritura.

¿Hay algún beneficio por elegir uno sobre el otro?

Estos deberían explicarse por sí solos ahora. La opción 1 (extender) se considera más limpia y es imprescindible si está modificando prototipos extranjeros/desconocidos/nativos. Intente evitar la opción 2.

Si todavía te gusta más la sintaxis literal del objeto, deberías considerar usarla Object.assignpara ampliar el prototipo existente:

Object.assign(Person.prototype, {
   sayName: function(name) {
      alert(name);
   }
});

Es posible que necesites realizar un polyfillObject.assign para entornos anteriores a ES6. Alternativamente, $.extendo _.extendfunciona igual de bien. Seguro que tu biblioteca favorita también viene con una función auxiliar para ello.

Bergi avatar Jul 04 '2013 16:07 Bergi

El segundo sobrescribirá person.prototype con el objeto.

Método uno:

Object.toString=function(){
  return "Object to string";
}
var Person = function(){
};
Person.toString=function(){
  return "Person to string";
}
Person.prototype.sayName=function(){}
console.log(Person.prototype.constructor.toString());// "Person to string"

Método dos:

Object.toString=function(){
  return "Object to string";
}
var Person = function(){
};
Person.toString=function(){
  return "Person to string";
}
Person.prototype = {
  sayName:function(){}
}
console.log(Person.prototype.constructor.toString());// "Object to string"
HMR avatar Jul 04 '2013 16:07 HMR

El primero sirve para una o dos funciones extra, pero definir un prototipo totalmente nuevo con muchas funciones sería muy repetitivo. Por otro lado, hacer esto último destruiría todas las definiciones existentes para el prototipo como mencionaste.

En la práctica, he usado el primero para definir funciones adicionales en Array y Math, etc., algo así como categorías en Objective-C. Este último lo uso como "definición de clase".

isaach1000 avatar Jul 04 '2013 16:07 isaach1000

Cualquier instancia existente del constructor seguirá apuntando al antiguo objeto prototipo. Cualquier nueva instancia creada apuntará al nuevo objeto prototipo.


Las ventajas de la opción 1 sobre la opción 2 son simplemente que no es necesario restablecer la propiedad del constructor y se ahorra un nivel de sangría, lo cual es enorme para mí.

Para ahorrar repeticiones, simplemente asigno la propiedad a una variable local:

var method = Person.prototype;

method.getAge = function() {
    return this.age;
};

method.getName = function() {
    return this.name;
};

También son opciones comunes fn(jQuery) y pque son incluso más cortas que method.

Esailija avatar Jul 04 '2013 17:07 Esailija