Herança (JavaScript Advanced Programming Capítulo 6 Core Knowledge Notes (2))

herdar

6.3.1 Cadeia de protótipo

Cadeia de protótipo como o principal método de herança: a ideia básica é usar o protótipo para permitir que um tipo de referência herde as propriedades e métodos de outro tipo de referência

Insira a descrição da imagem aqui

		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

O código acima define dois construtores: SuperTypee Subtype, cada tipo possui uma propriedade e um método, a principal diferença entre eles é a SubTypeherança SuperType.

A herança é obtida criando SuperTypeuma instância e atribuindo a instância à SubType.prototyperealização.

A essência da implementação é reescrever o objeto de protótipo e substituí-lo por uma instância de um novo tipo. Em outras palavras, SuperTypeas propriedades e métodos que existiam originalmente em agora também existem em SubType.prototype.

Depois de estabelecer a relação de herança, SubType.prototypeadicionamos um método, para SuperTypeque um novo método fosse adicionado com base nas propriedades e métodos herdados .

O resultado final é este:

instanceSubTypeProtótipo pontiagudo

SubTypeProtótipo e SuperTypeprotótipo dirigido

getSuperValue()Ainda no SuperType.prototypemeio, mas propertyno SubType.prototypemeio. Isso ocorre porque propertyé uma propriedade de instância, mas getSuperValue()um método de protótipo

  • Observação: instance.constructoragora está apontando para o SuperTypemotivo de isso ser porque o SubType.prototypeconstrutor original foi reescrito.

  • Determine a relação entre protótipo e instância:

    1. instanceofOperador
    2. isPrototypeOf()método
  • Desvantagens da herança da cadeia de protótipo:

    1. Todas as instâncias do construtor filho compartilharão a definição do construtor pai 引用类型值属性.

      		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"
      

      As nossas instance1.colorsalterações podem ser instance2.colorsrefletidas, o que provou plenamente este ponto.

    2. Ao criar uma instância de um subtipo, você não pode passar parâmetros para o construtor do supertipo.

6.3.2 Construtor de empréstimo

Para resolver os problemas causados ​​pela inclusão de valores de tipo de referência na cadeia de protótipos, os desenvolvedores começaram a usar uma técnica chamada construtores emprestados.

  • A ideia básica: chamar o construtor do supertipo dentro do construtor do subtipo (a função é apenas um objeto que executa o código em um ambiente específico, então o construtor também pode ser executado no objeto recém-criado usando os métodos apply () e 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"
    

    A linha de fundo no código "secundou" o construtor do supertipo.

    Ao usar o call()``和apply()método, realmente SubTypechamamos o SuperTypeconstrutor no ambiente da instância recém-criada .

    Desta forma, todos os códigos de inicialização do objeto definidos na função serão SubTypeexecutados no novo objeto SuperType(), SubTypee todas as instâncias do resultado terão colorscópias de suas próprias propriedades.

  • Parâmetros de passagem

    Em comparação com a herança da cadeia de protótipo, tomar emprestado o construtor tem uma grande vantagem.Você pode passar parâmetros para o construtor do supertipo no construtor do 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
    
  • O problema de pegar emprestado o construtor

    Se você apenas pegar emprestado o construtor, não poderá evitar o problema do modo do construtor. Os métodos são definidos no construtor, portanto, não há como falar sobre reutilização de função.

    Os métodos definidos no protótipo do supertipo não são visíveis para o subtipo.

6.3.3 Herança combinada

  • Herança de combinação refere-se à combinação da cadeia de protótipo e a tecnologia de construtores de empréstimo

  • Idéia: Use a cadeia de protótipo para implementar a herança de propriedades e métodos de protótipo, e use o construtor para implementar a herança de propriedades de instância.

  • Ele não apenas realiza a reutilização de funções definindo métodos no protótipo, mas também garante que cada instância tenha suas próprias propriedades.

            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
    

    Neste exemplo, SuperTypedois atributos são definidos: namee colors.

    SuperTypeO protótipo define um método sayName().

    SubTypeO construtor SuperTypepassa nameparâmetros ao chamar o construtor e, em seguida, define suas próprias propriedades age.

    Em seguida, atribua SuperTypea instância ao SubTypeprotótipo e defina o método no protótiposayAge()

    Dessa forma, duas SubTypeinstâncias diferentes podem ter seus próprios atributos, incluindo colorsatributos, e podem usar o mesmo método.

  • A herança combinatória evita os defeitos da cadeia de protótipo e da herança do construtor emprestado, combina suas vantagens e se torna o modo de herança mais comumente usado em JavaScript.

  • instanceofE isPrototypeOfser capaz de reconhecer objetos criados com base na herança combinada.

6.3.4 Herança de protótipo

Idéia: Com a ajuda de protótipos, novos objetos podem ser criados com base em objetos existentes sem a necessidade de criar tipos personalizados.

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

Dentro da função object (), um construtor temporário é criado e, em seguida, o objeto passado é usado como o protótipo do construtor e, finalmente, uma nova instância de um tipo temporário é retornada. Essencialmente, object () executa uma cópia superficial do objeto passado.

        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 Herança parasitária

  • A herança parasitária é uma ideia intimamente relacionada à herança do protótipo

  • Ideia: Criar uma função que só serve para encapsular o processo de herança.A função aprimora internamente o objeto de uma certa maneira e, finalmente, retorna o objeto como se ele realmente fizesse todo o trabalho.

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

6.3.6 Herança combinada parasitária

A herança combinatória é o padrão de herança mais comumente usado em JavaScript, mas também tem suas próprias deficiências. O maior problema com a herança combinatória é que não importa qual seja a situação, o construtor do supertipo será chamado duas vezes: uma ao criar o protótipo da subclasse e outra vez dentro do construtor da subclasse.

        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);
        };

Ao chamar a SuperType()função pela primeira vez , SuperType.prototypevocê obterá duas propriedades: name, colors; Ambas são SuperTypepropriedades de instância, mas agora estão no SubTypeprotótipo. Quando o SubTypeconstrutor é chamado, o construtor é chamado novamente SuperType, desta vez criando atributos de instância namee no novo objeto colors. Portanto, este atributo bloqueia os dois atributos com o mesmo nome no protótipo.

Em outras palavras, existem dois conjuntos de atributos de nome e cores: um definido no exemplo e outro definido no SubTypeprotótipo. Este é SubTypeo resultado de chamar o construtor duas vezes .

Felizmente, encontramos uma maneira de resolver esse problema de herança combinada parasita.

  • Herança combinada de parasitas: herde propriedades emprestando construtores e herde métodos por meio de formas mistas de cadeia de protótipo

  • A ideia básica: você não precisa chamar o construtor do supertipo para especificar o protótipo do subtipo.O que queremos nada mais é do que uma cópia do protótipo do supertipo.

  • Essência: Use a herança parasitária para herdar o protótipo do supertipo e, em seguida, atribua o resultado ao protótipo do subtipo. O padrão básico de herança combinada parasitária é o seguinte:

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

A eficiência deste exemplo é refletida no fato de que ele chama o SuperTypeconstrutor apenas uma vez e, portanto, evita a SubType.prototypecriação de propriedades desnecessárias e redundantes nele. Ao mesmo tempo, a cadeia de protótipo pode permanecer inalterada; ela também pode ser usada instanceofeisPrototypeOf()

Acho que você gosta

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