Herencia (Programación avanzada de JavaScript Capítulo 6 Notas de conocimientos básicos (2))

heredar

6.3.1 Cadena de prototipos

Cadena de prototipos como método principal de herencia: la idea básica es utilizar el prototipo para permitir que un tipo de referencia herede las propiedades y métodos de otro tipo de referencia.

Inserte la descripción de la imagen aquí

		function SuperType(){
    
    
            this.property = true;
        }
        
        SuperType.prototype.getSuperValue = function(){
    
    
            return this.property;
        };
        
        function SubType(){
    
    
            this.subproperty = false;
        }
        
        //inherit from SuperType
        SubType.prototype = new SuperType();
        
        SubType.prototype.getSubValue = function (){
    
    
            return this.subproperty;
        };
        
        var instance = new SubType();
        alert(instance.getSuperValue());   //true
       
        alert(instance instanceof Object);      //true
        alert(instance instanceof SuperType);   //true
        alert(instance instanceof SubType);     //true

        alert(Object.prototype.isPrototypeOf(instance));    //true
        alert(SuperType.prototype.isPrototypeOf(instance)); //true
        alert(SubType.prototype.isPrototypeOf(instance));   //true

El código anterior define dos constructores: SuperTypey Subtype, cada tipo tiene una propiedad y un método, la principal diferencia entre ellos es la SubTypeherencia SuperType.

La herencia se logra creando SuperTypeuna instancia y asignándola a la SubType.prototyperealización.

La esencia de la implementación es reescribir el objeto prototipo y reemplazarlo con una instancia de un nuevo tipo. En otras palabras, SuperTypelas propiedades y métodos que existían originalmente en ahora también existen en SubType.prototype.

Después de establecer la relación de herencia, SubType.prototypeagregamos un método, de modo SuperTypeque se agregó un nuevo método sobre la base de las propiedades y métodos heredados .

El resultado final es este:

instanceSubTypePrototipo puntiagudo

SubTypePrototipo y SuperTypeprototipo dirigido

getSuperValue()Todavía en el SuperType.prototypemedio, pero propertyen el SubType.prototypemedio. Esto se debe a que propertyes una propiedad de instancia, pero getSuperValue()un método prototipo

  • Nota: instance.constructorAhora señala la SuperTyperazón por la que esto se debe a que el SubType.prototypeconstructor original se ha reescrito.

  • Determine la relación entre el prototipo y la instancia:

    1. instanceofOperador
    2. isPrototypeOf()método
  • Desventajas de la herencia de la cadena de prototipos:

    1. Todas las instancias del constructor hijo compartirán la definición del constructor padre 引用类型值属性.

      		function SuperType(){
              
              
                  this.colors = ["red", "blue", "green"];
              }
      
              function SubType(){
              
                          
              }
              
              //inherit from SuperType
              SubType.prototype = new SuperType();
      
              var instance1 = new SubType();
              instance1.colors.push("black");
              alert(instance1.colors);    //"red,blue,green,black"
              
              var instance2 = new SubType();
              alert(instance2.colors);    //"red,blue,green,black"
      

      Nuestras instance1.colorsenmiendas pueden instance2.colorsreflejarse, lo que ha demostrado plenamente este punto.

    2. Al crear una instancia de un subtipo, no puede pasar parámetros al constructor del supertipo.

6.3.2 Constructor de préstamos

Para resolver los problemas causados ​​por la inclusión de valores de tipo de referencia en la cadena del prototipo, los desarrolladores comenzaron a utilizar una técnica llamada constructores prestados.

  • La idea básica: llamar al constructor de supertipo dentro del constructor de subtipo (la función es solo un objeto que ejecuta código en un entorno específico, por lo que el constructor también se puede ejecutar en el objeto recién creado usando los métodos apply () y call () .

    		function SuperType(){
          
          
                this.colors = ["red", "blue", "green"];
            }
    
            function SubType(){
          
            
                // inherit from SuperType
                // here, this will point to instance of SubType
                SuperType.call(this);
            }
    
            var instance1 = new SubType();
            instance1.colors.push("black");
            alert(instance1.colors);    //"red,blue,green,black"
            
            var instance2 = new SubType();
            alert(instance2.colors);    //"red,blue,green"
    

    La línea de fondo en el código "secundó" al constructor de supertipo.

    Al usar el call()``和apply()método, en realidad SubTypellamamos al SuperTypeconstructor en el entorno de la instancia recién creada .

    De esta manera, todos los códigos de inicialización de objeto definidos en la función se SubTypeejecutarán en el nuevo objeto y todas las instancias del SuperType()resultado SubTypetendrán colorscopias de sus propias propiedades.

  • Pasar parámetros

    En comparación con la herencia de la cadena de prototipos, tomar prestado el constructor tiene una gran ventaja: puede pasar parámetros al constructor de supertipo en el constructor de subtipo.

            function SuperType(name){
          
          
                this.name = name;
            }
    
            function SubType(){
          
            
                //inherit from SuperType passing in an argument
                SuperType.call(this, "Nicholas");
                
                //instance property
                this.age = 29;
            }
    
            var instance = new SubType();
            alert(instance.name);    //"Nicholas";
            alert(instance.age);     //29
    
  • El problema de pedir prestado al constructor

    Si solo toma prestado el constructor, entonces no puede evitar el problema del modo constructor Los métodos están definidos en el constructor, por lo que no hay forma de hablar sobre la reutilización de funciones.

    Los métodos definidos en el prototipo del supertipo no son visibles para el subtipo.

6.3.3 Herencia combinada

  • La herencia combinada se refiere a la combinación de la cadena de prototipos y la tecnología de los constructores prestatarios.

  • Idea: use la cadena de prototipos para implementar la herencia de propiedades y métodos de prototipos, y use el constructor para implementar la herencia de propiedades de instancia.

  • No solo se da cuenta de la reutilización de funciones mediante la definición de métodos en el prototipo, sino que también asegura que cada instancia tenga sus propias propiedades.

            function SuperType(name){
          
          
                this.name = name;
                this.colors = ["red", "blue", "green"];
            }
            
            SuperType.prototype.sayName = function(){
          
          
                alert(this.name);
            };
    
            function SubType(name, age){
          
            
                // 继承属性
                SuperType.call(this, name);
                
                this.age = age;
            }
    
    		// 继承方法
            SubType.prototype = new SuperType();
            SubType.prototype.constructor = SubType;
            SubType.prototype.sayAge = function(){
          
          
                alert(this.age);
            };
            
            var instance1 = new SubType("Nicholas", 29);
            instance1.colors.push("black");
            alert(instance1.colors);  //"red,blue,green,black"
            instance1.sayName();      //"Nicholas";
            instance1.sayAge();       //29
            
           
            var instance2 = new SubType("Greg", 27);
            alert(instance2.colors);  //"red,blue,green"
            instance2.sayName();      //"Greg";
            instance2.sayAge();       //27
    

    En este ejemplo, se SuperTypedefinen dos atributos: namey colors.

    SuperTypeEl prototipo define un método sayName().

    SubTypeEl constructor SuperTypepasa nameparámetros cuando llama al constructor y luego define sus propias propiedades age.

    Luego, asigne SuperTypela instancia al SubTypeprototipo y luego defina el método en el prototiposayAge()

    De esta manera, dos SubTypeinstancias diferentes pueden tener sus propios atributos, incluidos los colorsatributos, y pueden utilizar el mismo método.

  • La herencia combinatoria evita los defectos de la cadena de prototipos y la herencia del constructor prestado, combina sus ventajas y se convierte en el modo de herencia más utilizado en JavaScript.

  • instanceofY isPrototypeOfser capaz de reconocer objetos creados en base a la herencia combinada.

6.3.4 Herencia de prototipos

Idea: Con la ayuda de prototipos, se pueden crear nuevos objetos basados ​​en objetos existentes sin tener que crear tipos personalizados.

function object(o) {
    
    
    function F() {
    
    };
    F.prototype = o;
    return new F();
}

Dentro de la función object (), se crea un constructor temporal, y luego el objeto pasado se usa como prototipo del constructor, y finalmente se devuelve una nueva instancia de un tipo temporal. Esencialmente, object () realiza una copia superficial del objeto pasado.

        function object(o){
    
    
            function F(){
    
    }
            F.prototype = o;
            return new F();
        }
        
        var person = {
    
    
            name: "Nicholas",
            friends: ["Shelby", "Court", "Van"]
        };
        
        var anotherPerson = object(person);
        anotherPerson.name = "Greg";
        anotherPerson.friends.push("Rob");
        
        var yetAnotherPerson = object(person);
        yetAnotherPerson.name = "Linda";
        yetAnotherPerson.friends.push("Barbie");
        
        alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"

6.3.5 Herencia parasitaria

  • La herencia parasitaria es una idea estrechamente relacionada con la herencia de prototipos

  • Idea: Crea una función que solo se use para encapsular el proceso de herencia, la función mejora internamente el objeto de cierta manera y finalmente devuelve el objeto como si realmente hiciera todo el trabajo.

    function createAnother(original) {
          
          
        var clone = object(original)  // 通过调用函数创建一个新对象
        clone.sayHi = function() {
          
              // 以某种方式来增强这个对象
            alert("hi")
        }
        return clone  // 返回这个对象
    }
    

6.3.6 Herencia combinada de parásitos

La herencia combinatoria es el patrón de herencia más utilizado en JavaScript, pero también tiene sus propias deficiencias. El mayor problema con la herencia combinatoria es que no importa cuál sea la situación, el constructor de supertipo se llamará dos veces: una vez al crear el prototipo de subclase y la otra vez dentro del constructor de subclase.

        function SuperType(name){
    
    
            this.name = name;
            this.colors = ["red", "blue", "green"];
        }
        
        SuperType.prototype.sayName = function(){
    
    
            alert(this.name);
        };

        function SubType(name, age){
    
      
            // 继承属性
            SuperType.call(this, name); // 第二次调用SuperType()
            
            this.age = age;
        }

		// 继承方法
        SubType.prototype = new SuperType(); // 第一次调用 SuperType()
        SubType.prototype.constructor = SubType;
        SubType.prototype.sayAge = function(){
    
    
            alert(this.age);
        };

Cuando llame a la SuperType()función por primera vez , SuperType.prototypeobtendrá dos propiedades: name, colors; Ambas son SuperTypepropiedades de instancia, pero ahora están en SubTypeel prototipo. Cuando SubTypese llama al constructor, se vuelve a llamar al constructor SuperType, esta vez creando atributos de instancia namey sobre el nuevo objeto colors. Por tanto, este atributo bloquea los dos atributos con el mismo nombre en el prototipo.

En otras palabras, hay dos conjuntos de atributos de nombre y colores: uno en el ejemplo y otro en el SubTypeprototipo. Este es SubTypeel resultado de llamar al constructor dos veces .

Afortunadamente, hemos encontrado una manera de resolver este problema de herencia combinada parasitaria.

  • Herencia combinada de parásitos: hereda propiedades tomando prestados constructores y hereda métodos a través de formas mixtas de cadena de prototipos

  • La idea básica: no es necesario llamar al constructor del supertipo para especificar el prototipo del subtipo, lo que queremos es nada más que una copia del prototipo del supertipo.

  • Esencia: utilice la herencia parasitaria para heredar el prototipo del supertipo y luego asigne el resultado al prototipo del subtipo. El patrón básico de herencia combinada parasitaria es el siguiente:

function inheritPrototype(subType, superType) {
    
    
    var prototype = object(superType.prototype) // 创建对象(超类型原型的一个副本)
    prototype.constructor = subType // 增强对象(为创建的副本添加constructor属性)
    subType.prototype = prototype // 指定对象
}
        function object(o){
    
    
            function F(){
    
    }
            F.prototype = o;
            return new F();
        }
    
        function inheritPrototype(subType, superType){
    
    
            var prototype = object(superType.prototype);   //create object
            prototype.constructor = subType;               //augment object
            subType.prototype = prototype;                 //assign object
        }
                                
        function SuperType(name){
    
    
            this.name = name;
            this.colors = ["red", "blue", "green"];
        }
        
        SuperType.prototype.sayName = function(){
    
    
            alert(this.name);
        };

        function SubType(name, age){
    
      
            SuperType.call(this, name);
            
            this.age = age;
        }

        inheritPrototype(SubType, SuperType);
        
        SubType.prototype.sayAge = function(){
    
    
            alert(this.age);
        };
        
        var instance1 = new SubType("Nicholas", 29);
        instance1.colors.push("black");
        alert(instance1.colors);  //"red,blue,green,black"
        instance1.sayName();      //"Nicholas";
        instance1.sayAge();       //29
        
       
        var instance2 = new SubType("Greg", 27);
        alert(instance2.colors);  //"red,blue,green"
        instance2.sayName();      //"Greg";
        instance2.sayAge();       //27

La eficiencia de este ejemplo se refleja en que solo llama al SuperTypeconstructor una vez y, por lo tanto, evita SubType.prototypecrear propiedades innecesarias y redundantes en él. Al mismo tiempo, la cadena de prototipos puede permanecer sin cambios; también se puede utilizar instanceofyisPrototypeOf()

Supongo que te gusta

Origin blog.csdn.net/qq_27575925/article/details/111712955
Recomendado
Clasificación