Se acordó la explicación de la herencia de JavaScript, pero se ha retrasado. Sin más preámbulos, solo llega al punto.
Como desea comprender la herencia, demuestra que ya tiene una cierta comprensión de JavaScript orientado a los objetos. Si no comprende nada, puede consultar la explicación básica de JS orientado a objetos, modo de fábrica, modo constructor, modo prototipo, modo mixto, modo prototipo dinámico ". A continuación, hablemos sobre la herencia de JavaScript generalmente a través de esos métodos.
Cadena prototipo
La forma más fácil de implementar la herencia en JavaScript es usar una cadena de prototipo y apuntar el prototipo del tipo de niño a una instancia del tipo principal, es decir, "subtype.prototype = new Parent Type ();". El método de implementación es el siguiente:
// Crear una función de constructor supertype () {this.name = ['wuyuchang', 'jack', 'tim']; this.property = true;} // Agregar método supertype.prototype.getSuerpervalue = function () {return this.property;} // crea una función de constructor subtype () {this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false;} // Pasos clave para implementar la herencia, el prototipo del subtipo apunta a una instancia del tipo principal subtype.prototype = new SuperType (); // Agregar un método al tipo de hijo aquí. Debe ser después de implementar la herencia, de lo contrario, el puntero se apuntará a una instancia del tipo principal, y el método está vacío. Subtype.prototype.getSubValue = function () {return this.subproperty;}/* El siguiente es un ejemplo de código de prueba*/var instance1 = new subtype (); instancia1.name.push ('wyc'); instancia1.test.push ('h5'); alerta (instancia1.getsuerpervalue ()); // trueLert (instancia1.getSubValue ()); // falsealert (instancia1.name); // Wuyuchang, Jack, Tim, Wycalert (instancia1.test); // H1, H2, H3, H4, H5VAR instance2 = new Subtype (); alerta (instancia2.name); // Wuyuchang, Jack, Tim, Wycalert (instancia2.test); // H1, H2, H3, H4Puede ver que el código anterior es una herencia simple implementada a través de la cadena prototipo, pero todavía hay algunos problemas en el ejemplo del código de prueba. Creo que después de leer mi publicación de blog "Explicación básica del JS orientado a objetos, el modo de fábrica, el modo del constructor, el modo prototipo, el modo mixto, el modo prototipo dinámico", debo saber que el primer problema con el código de la cadena prototipo es que el prototipo del subtifpe es una instancia del tipo principal, es decir, el tipo El valor de tipo será compartido por todas las instancias . La instancia1.name.push ('wyc'); del código anterior puede probar la existencia de este problema. El segundo problema con la cadena prototipo es que al crear una instancia de un subtipo, los parámetros no se pueden pasar al constructor supertipo . Por lo tanto, en el desarrollo real, rara vez usamos cadenas prototipo solas.
Constructor de préstamo
Para resolver dos problemas en la cadena prototipo, los desarrolladores comenzaron a usar una técnica llamada constructores de préstamos para resolver problemas en la cadena prototipo. La idea de implementación de esta tecnología también es bastante simple. Solo necesita llamar al constructor del tipo principal dentro del constructor del subtipo. No olvide que las funciones son solo objetos que ejecutan el código en un entorno específico, por lo que los constructores pueden ejecutarse a través del método Aplicar () o llamar () . El código es el siguiente:
// Crear una función de constructor supertype (name) {this.name = name; this.color = ['rosa', 'amarillo']; this.property = true; this.testfun = function () {alert ('http://tools.vevb.com/'); }} // Agregar método supertype.prototype.getSuerperValue = function () {return this.property;} // crea una función de constructor subtype (name) {supertype.call (this, name); this.test = ['H1', 'H2', 'H3', 'H4']; this.subproperty = false;} // Agregue un método al subtipo aquí. Be sure to implement inheritance, otherwise the pointer will be pointed to an instance of the parent type, and the method is empty SubType.prototype.getSubValue = function() { return this.subproperty;}/* The following is a test code example*/var instance1 = new SubType(['wuyuchang', 'Jack', 'Nick']); instance1.name.push ('hello'); instance1.test.push ('h5'); instancia1.color.push ('azul'); instancia1.testfun (); // http://tools.vevb.com/alert(instance1.name); // wuyuchang, jack, nick, hola // alerta (instancia1.getSuerperValue ()); // Alerta de error (instancia1.test); // H1, H2, H3, H4, H5 alerta (instancia1.getSubValue ()); // alerta falsa (instancia1.color); // rosa, amarillo, bluevar instancia2 = nuevo subtipo ('wyc'); instancia2.testfun (); // http://tools.vevb.com/alert(instance2.name); // wyc // alerta (instancia2.getSuerperValue ()); // Alerta de error (instancia2.test); // H1, H2, H3, H4Alert (instance2.getSubValue ()); // falsealert (instance2.color); // rosa, amarilloPuede ver que en el código anterior, el constructor del subtipo de subtipo en el código anterior, la herencia del atributo se realiza llamando al tipo principal "Supertype.call (this, nombre);". También puede pasar parámetros al tipo principal cuando se crea el subtipo, pero se acerca un nuevo problema. Puede ver que definí un método en el constructor del tipo principal: TestFun, y un método en el prototipo del tipo principal: GetuperValue. Sin embargo, después de instanciar el subtipo, todavía es imposible llamar al método GetuperValue definido en el prototipo del tipo principal , y solo puede llamar al método del constructor en el tipo principal: TestFun. Esto es lo mismo que usar solo el modo Constructor en la creación de objetos, para que la función no tenga reutilización. Teniendo en cuenta estos problemas, las técnicas de los constructores de préstamos rara vez se usan solos.
Herencia combinada (cadena prototipo + constructor de préstamo)
Como su nombre indica, la herencia combinada es un patrón compuesto por las ventajas de combinar el uso de cadenas prototipo y constructores de préstamos. La implementación también es muy simple. Dado que es una combinación, por supuesto, combina las ventajas de ambas partes, a saber, el método de herencia de la cadena prototipo, y el constructor hereda los atributos . El código específico se implementa de la siguiente manera:
// Crear una función de constructor supertype (name) {this.name = name; this.color = ['rosa', 'amarillo']; this.property = true; this.testfun = function () {alert ('http://tools.vevb.com/'); }} // Agregar método supertype.prototype.getSuerperValue = function () {return this.property;} // crea una función de constructor subtype (name) {supertype.call (this, name); this.test = ['H1', 'H2', 'H3', 'H4']; this.subproperty = false;} subtype.prototype = new SuperType (); // Agregue un método al subtipo aquí. Debe ser después de que se implementa la herencia, de lo contrario, el puntero se apuntará a una instancia del tipo principal, y el método está vacío subtype.prototype.getSubValue = function () {return this.subproperty;}/* El siguiente es un ejemplo de código de prueba*/var instancia1 = nuevo subtype (['wuyuchang', 'jack',,,,, es un ejemplo de código de prueba*/var instancia1 = nuevo subtype (['wuyuchang', 'jack',,,,, jack ',, es un ejemplo de código de prueba*/var instancia1 = nuevo subtype ([' wuyuchang ',' jack ',,,,, jack',,, es un ejemplo de código de prueba*/var instancia1 = nuevo subtype (['wuyuchang', 'jack',,, jack ',,, es un ejemplo de código de prueba*/var instancia1 = nuevo subtype ([' wuyuchang ',' jack ',,, jack',,. 'Nick']); instance1.name.push ('hello'); instance1.test.push ('h5'); instancia1.color.push ('azul'); instancia1.testfun (); // http://tools.vevb.com/alert(instance1.name); // Wuyuchang, Jack, Nick, Helloalert (instance1.getSuerperValue ()); // TRUEALERT (instancia1.test); // H1, H2, H3, H4, H5 alerta (instancia1.getSubValue ()); // alerta falsa (instancia1.color); // rosa, amarillo, bluevar instancia2 = nuevo subtipo ('wyc'); instancia2.testfun (); // http://tools.vevb.com/alert(instance2.name); // alerta wyc (instancia2.getSuerperValue ()); // TRUEALERT (instancia2.test); // H1, H2, H3, H4Alert (instance2.getSubValue ()); // falsealert (instance2.color); // rosa, amarilloEl código anterior hereda las propiedades del tipo principal a través de Supertype.call (este, nombre); y hereda los métodos del tipo principal a través de subtipo.prototype = new SuperType ();. El código anterior resuelve convenientemente los problemas encontrados por las cadenas prototipo y los constructores de préstamos, y se ha convertido en el método de herencia de instancias más utilizado en JavaScript. Sin embargo, el modo mixto no está exento de deficiencias. Se puede ver que en el código anterior, los atributos del tipo principal se han heredado al heredar el método. Sin embargo, el tipo de referencia se comparte en este momento. Por lo tanto, el constructor del tipo principal se llama en el constructor del tipo de niño después del subtipo, heredando así los atributos del tipo principal para sobrescribir los atributos heredados en el prototipo. Obviamente no es necesario llamar al constructor dos veces, pero ¿hay alguna forma de resolverlo? Al resolver este problema, primero mire los siguientes dos modos.
Herencia prototipo
El método de implementación de herencia prototipo es diferente al de la herencia ordinaria. La herencia prototipo no usa un constructor en el sentido estricto, sino que usa el prototipo para crear nuevos objetos basados en objetos existentes, y no es necesario crear tipos personalizados como resultado. El código específico es el siguiente:
objeto de función (o) {function f () {} f.prototype = o; devolver nuevo f ();}Ejemplo de código:
/* Prototipo de herencia*/objeto de función (o) {function f () {} f.prototype = o; return new f ();} var persona = {nombre: 'wuyuchang', amigos: ['wyc', 'nicholas', 'tim']} var otroperson = objeto (persona); otroperson.name = 'Greg'; otroperson.friends.push ('bob'); var otroperson2 = objeto (persona); otra persona2.name = 'jack'; otroperson2.fiends.push ('rosa'); alerta (persona.riends); // Wyc, Nicholas, Tim, Bob, RoseHerencia parásita
/* Herencia parásita*/function createAnother (original) {var clone = object (original); clone.sayhi = function () {alert ('Hi'); } clon de retorno;}Ejemplo de uso:
/* Prototipo de herencia*/objeto de función (o) {function f () {} f.prototype = o; return new f ();} /* herencia parásita* /function createAnother (original) {var clone = object (original); clone.sayhi = function () {alert ('Hi'); } return clone;} var persona = {nombre: 'wuyuchang', amigos: ['wyc', 'nicholas', 'rosa']} var otro porterson = createAther (persona); otra persona.sayhi ();Herencia de combinación parásita
Mencioné anteriormente las desventajas de la implementación del patrón de combinación de la herencia en JavaScript. Ahora resolvamos sus deficiencias. La idea de implementación es heredar atributos para constructores, y el método de herencia de forma mixta de la cadena prototipo no necesita instanciar el constructor del tipo principal al heredar el método. El código es el siguiente:
objeto de función (o) {function f () {} f.prototype = o; return new f ();}/* herencia de combinación parásita*/function hereitprototype (subtype, supertype) {var prototype = object (supertype.prototype); prototipo.constructor = subtype; subtype.prototype = prototipo;}Al usarlo, solo necesita reemplazar la línea de código "subtype.prototype = new SuperType ();" en el modo de combinación con herhheritprototype (subtipo, supertype);. La eficiencia de la herencia combinatoria parásita se refleja en que llama al constructor de tipo principal solo una vez, evitando la creación de propiedades innecesarias o redundantes. Al mismo tiempo, la cadena prototipo puede permanecer sin cambios, por lo que instanciaf e isprototypeOf () también se puede usar normalmente. Este es también el método de herencia más ideal en la actualidad, y actualmente se está transformando en este modelo. (Yui también usa este modo).
Esta publicación de blog se refiere a "JavaScript Advanced Programming 3rd Edition". El código se reescribe y es más específico, y se comenta para que sea más fácil de entender para todos. Si tiene ideas únicas sobre la herencia JS, no seas tacaño. ¡Responda a sus opiniones para su referencia!