formato - ¿Hay una forma "correcta" de hacer herencia en JavaScript? Si es así, ¿qué es?
twig document (5)
He intentado aprender a agregar pruebas al código existente, actualmente leyendo lectura Trabajando eficazmente con código heredado . He intentado aplicar algunos de los principios en JavaScript, y ahora estoy tratando de extraer una interfaz.
Al buscar la creación de interfaces en JavaScript, no puedo encontrar mucho, y lo que encuentro sobre la herencia parece ser que hay varias formas diferentes. (Algunas personas crean sus propias clases base para proporcionar métodos útiles para facilitar la herencia, algunas funciones de uso y algunos prototipos de uso).
¿Cuál es el camino correcto? ¿Tienes un ejemplo simple para extraer una interfaz en JavaScript?
Estás viendo dos cosas diferentes.
Primero tienes interfaces. La forma más aceptada de implementar esto es a través de Duck Typing ("si se ve como un pato y grazna como un pato, entonces es un pato"). Esto significa que si un objeto implementa un conjunto de métodos de la interfaz, entonces es esa interfaz. Implementa esto teniendo una matriz de nombres de métodos que definen una interfaz. Luego, para verificar si un objeto implementa esa interferencia, verá si implementa esos métodos. Aquí hay un ejemplo de código que elevé:
function Implements(obj, inter)
{
var len = inter.length, i = 0;
for (; i < len; ++i)
{
if (!obj[inter[i]])
return false;
}
return true;
}
var IUser = ["LoadUser", "SaveUser"];
var user = {
LoadUser : function()
{
alert("Load");
},
SaveUser : function()
{
alert("Save");
}
};
var notUser = {
LoadUser : function()
{
alert("Load");
}
};
alert(Implements(user, IUser));
alert(Implements(notUser, IUser));
Ahora tienes herencia. JS no tiene herencia incorporada; entonces debes implementarlo manualmente. Esto es solo una cuestión de "copiar" las propiedades de un objeto a otro. Aquí hay otro ejemplo de código (no perfecto, pero demuestra el punto):
function InheritObject(base, obj)
{
for (name in base)
{
if (!obj[name])
obj[name] = base[name];
}
}
var Base = {
BaseFunc : function() { alert("BaseFunc from base"); },
InheritFunc : function() { alert("InheritFunc from base"); }
}
var Inherit = {
InheritFunc : function() { alert("InheritFunc from inherit"); },
AnotherFunc : function() { alert("AnotherFunc from inherit"); }
}
InheritObject(Base, Inherit);
Inherit.InheritFunc();
Inherit.BaseFunc();
Inherit.AnotherFunc();
Base.BaseFunc();
Base.InheritFunc();
Probablemente quiera mirar http://www.mootools.net . Tiene mi implementación favorita de Clases. También definitivamente debes consultar "Patrones de diseño de Pro Javascript"
http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X
Este libro entra en detalles sobre cómo emular OOP en javascript.
No hay un camino correcto definitivo, porque muchas personas están haciendo muchas cosas diferentes. Hay muchos patrones útiles.
Crockford sugiere que "vaya con el grano", o escriba javascript de una manera que corresponda a la naturaleza prototípica de JavaScript.
Por supuesto, continúa demostrando que el modelo original que sugirió Netscape está realmente roto. Él lo etiqueta como "pseudoclassical", y señala una gran cantidad de errores de dirección y la complejidad innecesaria que implica seguir ese modelo.
Él escribió la función "objeto" como un remedio (ahora conocido como Object.create ()). Permite algunos patrones prototípicos muy potentes.
No siempre es fácil desarrollar una interfaz limpia cuando tienes que trabajar con javascript heredado, especialmente no cuando trabajas con sistemas grandes, generalmente incluye varias bibliotecas y cada una implementa un estilo único y un patrón de herencia diferente. En general, diría que la "forma correcta" de hacer herencia es la que le permite escribir una interfaz limpia que se comporta bien en el contexto de su código heredado, pero también le permite refactorizar y eliminar antiguas dependencias con el tiempo. .
Teniendo en cuenta las diferencias entre los principales patrones de la biblioteca, he descubierto que la ruta más exitosa para realizar en mi propio trabajo es mantener mis interfaces independientes de las interfaces de la biblioteca por completo. Usaré una biblioteca o módulo si es útil, pero no estaré vinculado a él. Esto me ha permitido refactorizar una gran cantidad de código, eliminar algunas bibliotecas y utilizar bibliotecas como andamios que se pueden optimizar más adelante.
En esta línea, he escrito interfaces inspiradas en el patrón de herencia parasitaria de Crockford. Realmente es una victoria para la simplicidad.
En el otro lado de la moneda, estoy seguro de que podría abogar por elegir una biblioteca, imponerla en su equipo y ajustarse tanto a sus patrones de herencia como a sus convenciones de interfaz.
No hay clases en javascript, solo objetos.
Pero si insiste en emular el modelo orientado a objetos basado en clases, puede usar esto:
function ChildClass() { ParentClass.call(this); // Write the rest of your constructor function after this point. }; ChildClass.prototype = jQuery.extend({}, ParentClass.prototype, ChildClass.prototype);
jQuery.extend es una función de "copia superficial" de la biblioteca jQuery. Puede reemplazarlo con cualquier otra función de copia / clonación de objetos.
Prototype ofrece su propia versión de la herencia, de http://www.prototypejs.org/api/class/create :
var Animal = Class.create({
initialize: function(name, sound) {
this.name = name;
this.sound = sound;
},
speak: function() {
alert(this.name + " says: " + this.sound + "!");
}
});
// subclassing Animal
var Snake = Class.create(Animal, {
initialize: function($super, name) {
$super(name, ''hissssssssss'');
}
});
También echa un vistazo a Dean Edwards ''Base.js. Puedes echarle un vistazo aquí , la publicación del blog es autoexplicativa.