Si realmente no puede entender algún conocimiento en ese momento, puede dejarlo pasar por el momento y dejarlo en el futuro y tal vez pueda entenderlo.
Hace unos meses, estaba sosteniendo "JavaScript Advanced Programming (tercera edición)" y después de masticar la creación del objeto, comencé a masticar la herencia. Sin embargo, después de masticar la cadena prototipo, realmente no podía soportarlo más, y mi mente se volvió cada vez más desordenada, así que lo tiré a un lado y seguí mirando a este último. Ahora que he usado estas vacaciones de verano para comprender esta herencia, resolveré mis notas.
Encadenamiento prototipo
Leemos primero un artículo. El autor del artículo es muy bueno y está equipado con imágenes de alta definición. jajaja…
Enlace: [Notas de estudio] Ver la cadena prototipo JS desde una pequeña perspectiva
Unas pocas palabras del texto original
Determinar la relación entre prototipo e instancia
Hay dos formas de detectar la relación entre un prototipo y una instancia:
instanciaf: determina si el objeto es una instancia de otro objeto
El mecanismo informático interno de instanciaf es el siguiente:
functionInstance_of (l, r) {// l representa la expresión izquierda, r representa la expresión derecha varo = r.prototype; // tome el prototipo de visualización de r l = l .__ Proto__; // tomar el prototipo implícito de L while (verdadero) {if (l === null) returnfalse; if (o === l) // aquí el punto: cuando o es estrictamente igual a L, devuelva TrueReturnTrue; L = l .__ proto__; }}El código anterior se extrae de: análisis en profundidad del operador de instancia de JavaScript
isprototypeOf (): prueba si existe un objeto en la cadena prototipo de otro objeto
Consulte las diferencias entre estos dos métodos: JavaScript isprototypeOf vs instancia de uso
Solo use la cadena prototipo para lograr la herencia
Desventajas: 1. Los atributos prototipo que se refieren al valor de tipo serán compartidos por la instancia; 2. Al crear una instancia de un subtipo, los parámetros no se pueden pasar al constructor Supertype.
functather () {this.name = "padre"; this.friends = ['aaa', 'bbb'];} functionson () {} son.prototype = newfather (); son.prototype.constructor = son; vars1 = newson (); vars2 = neillOn (); console.log (s1.name); PatherConsole.log (s2.name); // fathers1.name = "hijo"; console.log (s1.name); // sonconsole.log (s2.name); // phathconsole.log (s1.friends); // ["aaa", "bbb"] console.log (s2.frienss); // ["aaa", aaa ", "bbb"] s1.friends.push ('ccc', 'ddd'); console.log (s1.friends); // ["aaa", "bbb", "ccc", "ddd"] console.log (s2.friends); // ["aaa", "bbb", "ccc", "ddd"]]]Solo use constructores para lograr la herencia
Método de implementación: llame al constructor Supertype dentro del constructor de subtipo (usando los métodos aplicar () y callar ())
Ventajas: resuelva el problema de hacer referencia a los atributos de tipo en el prototipo, y las subclases pueden pasar los parámetros a las superclases
Desventajas: las instancias de subclase no pueden acceder a los métodos definidos en el prototipo de clase principal (superclase), por lo que no hay forma de hablar sobre la reutilización de funciones.
functather (name, amigos) {this.name = name; this.friends = friends;} father.prototype.getName = function () {returnThis.name;}; functionson (name) {// nota: para asegurarse de que el padre no anule las propiedades del constructor del hijo, coloque el código que llama el padre antes de las propiedades definidas en el hijo. Padre.call (este, nombre, ['aaa', 'bbb']); this.age = 22;} vars1 = newson ('son1'); vars2 = newson ('son2'); console.log (s1.name); // son1console.log (s2.name); // son2s1.friends.push ('ccc', 'ddd'); console.log (s1.friends); // ["aaa", "bbb", "ccc", "ddd"] console.log (s2.friends); // ["aaa", "bbb"] // subclass instancia no puede acceder al método s1.getName () en el patrón de patrón; // typeError: s1.getName no es funciones 2.getName (); // typeError: s2.getName no es una funciónHerencia combinada
Método de implementación: use la cadena prototipo para implementar la herencia de las propiedades y métodos prototipo, y use el constructor para implementar la herencia de las propiedades de instancia.
functather (nombre, amigos) {this.name = name; this.friends = friends;} padre.prototype.money = "100k $"; padre.prototype.getName = function () {console.log (this.name);}; funciones (nombre, edad) {// Inherit la propiedad de la clase padre Padre.call (este, nombre, ['AAA', 'BBB']); this.age = Age;} // Heredir las propiedades y métodos en el prototipo de clase principal son.prototype = newfather (); son.protype.constructor = son; son.prototype.getage = function () {console.log (this.age);};};};};};};};};};};};};};};};}; = Newson ('son1', 12); s1.friends.push ('ccc'); console.log (s1.friends); // ["aaa", "bbb", "ccc"] console.log (s1.money); // 100k $ s1.getName (); // son1s1.getage (); // 12Vars2 = Newson ('son2', 24); console.log (s2.friends); // ["aaa", "bbb"] console.log (s2.money); // 100k $ s2.getName (); // son2s2.getage (); // 24La herencia combinada evita el defecto de unilateralmente utilizando cadenas prototipo o constructores para implementar la herencia, combina sus ventajas y se convierte en el modelo de herencia más utilizado en JavaScript, pero también es defectuoso, y el defecto de la herencia combinada se mencionará específicamente más adelante.
Herencia prototípica
Idea de implementación: use prototipos para crear nuevos objetos basados en objetos existentes, sin crear tipos personalizados debido a esto.
Para lograr esto, se introduce la siguiente función (OBJ)
functionObj (o) {funct () {} f.prototype = o; returnNewf ();} varperson1 = {name: "Percy", amigos: ['aaa', 'bbb']}; varperson2 = obj (persona1); persona2.name = "zyj"; persona2.fiends.push ('ccc'); consultor.LoG (persona1); Percyconsole.log (persona2.name); // zyjconsole.log (persona1.friends); // ["aaa", "bbb", "ccc"] console.log (persona2.friends); // ["AAA", "BBB", "CCC"] ECMAmet 5 normaliza el prototipo inheritancia por agregar el objeto. En el caso de pasar en un parámetro, los métodos Object.Create () y Obj () se comportan lo mismo. varperson1 = {name: "Percy", Friends: ['aaa', 'bbb']}; varperson2 = object.create (persona1); persona2.name = "zyj"; persona2.fiends.push ('ccc'); console.log (persona1.name); // percyconsole.log (persona2.name); ////// zyjconsole.log (persona1.friends); // ["aaa", "bbb", "ccc"] console.log (persona2.friends); // ["aaa", "bbb", "ccc"]]Esta herencia se puede elegir cuando no hay necesidad de movilizar al constructor para crearlo, pero solo quiere que un objeto permanezca similar a otro.
Herencia parásita
La herencia parásita es una idea estrechamente relacionada con la herencia prototipo.
Idea de implementación: cree una función que solo se use para encapsular el proceso de herencia, que mejora internamente el objeto de alguna manera y finalmente devuelve el objeto.
functionObj (o) {funct () {} f.prototype = o; returnNewf ();} functregeReperson (original) {// Encapsule Process de herencia varclone = obj (original); // Crear objeto clone.showsomting = function () {// mejore object console.log ("¡Hello World!"); }; returnClone; // Object de retorno} varperson = {nombre: "Percy"}; varperson1 = createperson (persona); console.log (persona1.name); // percyperson1.showsomthing (); // ¡Hola Mundo!Herencia de combinación parásita
Primero hablemos sobre las deficiencias de nuestra herencia de combinación anterior. El mayor problema con la herencia combinada es que no importa cuál sea la situación, el constructor de la clase principal se llamará dos veces: uno es cuando se crea el prototipo de la subclase, y el otro es cuando se llama al constructor de subclase, el constructor de la clase principal se llama dentro del constructor de subclase.
functather (nombre, amigos) {this.name = name; this.friends = friends;} padre.prototype.money = "100k $"; padre.prototype.getName = function () {console.log (this.name);}; funciones (nombre, edad) {// Inherit la propiedad de la clase padre Padre.call (este, nombre, ['aaa', 'bbb']); // La segunda llamada a padre () se llama en realidad este.age = edad;} // heredar las propiedades y métodos en el prototipo de clase principal son.prototype = newfather (); // el padre de la primera vez () se llama son.prototype.constructor = son;La primera llamada hace que el prototipo de la subclase sea una instancia de la clase principal, de modo que el prototipo de la subclase obtenga el atributo de instancia de la clase principal; La segunda llamada hará que el atributo de instancia de la subclase también obtenga el atributo de instancia de la clase principal; y el atributo de instancia de la subclase bloqueará los atributos que se duplican con el prototipo de subclase de forma predeterminada. Por lo tanto, después de estas dos llamadas, aparecen atributos innecesarios en el prototipo de subclase, introduciendo así la herencia de combinación parásita para resolver este problema.
La idea detrás de la herencia de la combinación parásita es: no hay necesidad de llamar al constructor de clase principal para especificar el prototipo de la subclase. Todo lo que necesitamos es una copia del prototipo de clase principal.
Esencialmente, es utilizar la herencia parásita para heredar el prototipo de la clase principal, y luego devolver el resultado al prototipo de la clase infantil.
functionObj (o) {funct () {} f.prototype = o; returnNewf ();} functionEnheritPrototype (son, padre) {varprototype = obj (padre.prototype); // crea objeto prototipo.constructor = son; // Mejorar objeto son.prototype = prototipo; // Return Object} ForceFather (Name, Friends) {this.name = name; this.friends = Friends;} Father.prototype.money = "100k $"; padre.prototype.getName = function () {console.log (this.name);}; Functionson (nombre, edad) {// Herit la propiedad de la clase pariente de la clase de los padres de la clase de los padres de la clase de la matriz Padre.call (este, nombre, ['aaa', 'bbb']); this.age = Age;} // heredar las propiedades y métodos en el prototipo de clase principal HereitPrototype (son, padre); son.prototype.getage = function () {console.log (this.age);}; vars1 = newson ('son1', 12); s1.riefr.push ('ccc'); console.log (s1.riends); ["aaa", "bbb", "ccc"] console.log (s1.money); // 100k $ s1.getName (); // son1s1.getage (); // 12Vars2 = Newson ('son2', 24); console.log (s2.friends); // ["aaa", "bbb"] console.log (s2.money); // 100k $ s2.getName (); // son2s2.getage (); // 24Ventajas: Haga que los prototipos de subclase eviten heredar las propiedades de instancia innecesaria en la clase principal.
Los desarrolladores generalmente creen que la herencia combinatoria parásita es el método de herencia más ideal basado en la herencia de tipo.
por fin
Finalmente, recomiendo dos artículos muy duros
JavaScript cómo funciona realmente la herencia prototípica
Diagrama de herencia pseudo clásica de JavaScript (necesita cruzar la pared)
Tome una imagen difícil del segundo artículo:
Después de leerlo, entiendo la cadena prototipo en segundos. ¿Hay algo?
Lo anterior es la recopilación de la información heredada por JavaScript. Continuaremos agregando información relevante en el futuro. ¡Gracias por su apoyo para este sitio web!