Maison >interface Web >js tutoriel >Introduction aux prototypes JavaScript et aux méthodes de chaîne de prototypes (exemples de code)

Introduction aux prototypes JavaScript et aux méthodes de chaîne de prototypes (exemples de code)

不言
不言avant
2019-01-10 10:59:442754parcourir

Cet article vous présente une introduction aux prototypes JavaScript et aux méthodes de chaîne de prototypes (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

1. Question

Comment déterminer avec précision si une variable est un tableau

Écrire un exemple d'héritage de chaîne de prototype

Autres modes de mise en œuvre de l'héritage

es6 Quel est le principe sous-jacent de l'héritage

Décrire le processus de création d'un nouvel objet

Comment utiliser la chaîne de prototypes dans zepto et autres codes sources

2. Points de connaissance

2.1 Constructeur

Caractéristiques : Commencez par une lettre majuscule

function Foo(name,age){
    //var obj = {}
    //this = {}
    this.name = name;
    this.age = age;
    this.class = 'class1'
    // return this
}

var f1 = new Foo('liming',19);

Développez

var o = {} est le sucre syntaxique pour var o = new Object()

var a = [] est le sucre syntaxique pour var a = new Array()

function Foo(){} tout à fait In var Foo = new Function(){}

2.2 Règles du prototype

Cinq règles :

1 . Tous les types de référence (objet, tableau, fonctions) ont tous des caractéristiques d'objet, c'est-à-dire que les attributs peuvent être librement étendus

2. Tous les types de référence (objets, tableaux, fonctions) ont un attribut __proto__ (prototype implicite). , qui est un objet ordinaire

3. Toutes les fonctions ont des attributs de prototype (prototype explicite) et sont également des objets ordinaires

4 Tous les types de référence (objets, tableaux, fonctions) pointent vers la valeur __proto__. le prototype de son constructeur

5. En essayant d'obtenir les attributs d'un objet, si la variable elle-même n'a pas cet attribut, elle ira dans son __proto__ pour le trouver

for (var key in object) {
    //高级浏览器中已经屏蔽了来自原型的属性
    //建议加上判断保证程序的健壮性
    if (object.hasOwnProperty(key)) {
        console.log(object[key]);
    }
}

2.3 Chaîne de prototypes

obj.__ proto . proto proto __ ...

Object.prototype = . == null

instanceof est utilisé pour déterminer à quel constructeur appartient le type de référence

obj instanceob Foo

Signification réelle : déterminer si Foo.prototype est sur la chaîne de prototypes de obj

3. Réponses aux questions

3.1 Comment déterminer avec précision si une variable est un tableau

arr instanceof Array

3.2 Écrire un exemple d'héritage de chaîne de prototypes

Avantages : Implémentation simple
function Elem(id){
    this.elem = document.getElementById(id);
};

Elem.prototype.html = function(val){
    var elem = this.elem;
    if (val) {
        elem.innerHTML = val;
        return this;
    }else{
        return elem.innerHTML;
    }
}

Elem.prototype.on = function(type,fun){
    var elem = this.elem;
    elem.addEventListener(type,fun);
    return this;
}

var p1 = new Elem('id1');
p1.html("test").on('click',function(){
    console.log('点击');
})

Inconvénients : 1 Impossible de transmettre les paramètres au constructeur de la classe parent

2. en même temps, lors de la modification de l'attribut de type de référence dans le prototype d'un objet, l'autre objet Cette propriété sera également modifiée. Parce que les propriétés de référence de l'objet prototype sont partagées par toutes les instances.

        var obj = {
            0:'a',
            1:'b',
            arr:[1]
        }
        
        function Foo(arr2){
            this.arr2 = [1]
        }

        Foo.prototype = obj;

        var foo1 = new Foo();
        var foo2 = new Foo();

        foo1.arr.push(2);
        foo1.arr2.push(2);

        console.log(foo2.arr);  //[1,2]
        console.log(foo2.arr2); //[1]
3.3.2 Héritage structurel

Avantages : Vous pouvez transmettre des paramètres à la classe parent, et la sous-classe ne partagera pas les attributs de référence de la classe parent

Inconvénients : Impossible d'implémenter les fonctions de réutilisation, chaque sous-classe a un nouveau plaisir, un trop grand nombre affectera les performances et l'objet prototype de la classe parent ne peut pas être hérité.

3.3.3 Héritage combiné

Avantages : Il n'y a aucun problème de partage des attributs de référence, les paramètres peuvent être transmis et les fonctions peuvent être réutilisées
        function Super(b){
            this.b = b;
            this.fun = function(){}
        }
        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }

        var foo1 = new Foo(1,2);
        console.log(foo1.b);

Inconvénients : Le les attributs de la classe parent seront instanciés deux fois, la classe parent de l'instance réelle ne pourra pas être obtenue (il est impossible de distinguer si l'instance est créée par la classe parent ou la classe parent)

Optimisation :

Inconvénient : Impossible de distinguer si l'instance est Si la classe parent est créée ou si la classe enfant est créée
function Super(){
    // 只在此处声明基本属性和引用属性
    this.val = 1;
    this.arr = [1];
}
//  在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
    Super.call(this);   // 核心
    // ...
}
Sub.prototype = new Super();

3.3.4 Héritage de combinaison parasite

Parasite le prototype de la classe parent une fois, c'est-à-dire l'envelopper dans un prototype d'objet vide, puis l'utiliser. L'objet est instancié en tant que sous-classe du péototype.

Inconvénients : Il est impossible de distinguer si une instance est créée par une classe parent ou une sous-classe
         function Super(b){
            this.b = b;
            this.fun = function(){}
        }

        Super.prototype.c = function(){console.log(1111)}

        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }


        Foo.prototype = Super.prototype;
        //修复构造函数:
        var foo1 = new Foo(1,2);

Vous pouvez ajouter le code suivant :

Cette solution ne peut pas être utilisé pour la méthode d'optimisation de combinaison ci-dessus, car la sous-classe et la classe parent font référence au même objet prototype, les modifications seront modifiées en même temps.
         function Super(b){
            this.b = b;
        }

        Super.prototype.c = function(){console.log(1111)}

        function Foo(a,b){
            this.a = a;
            Super.call(this,b);
        }

        var f = new Function();
        f.prototype = Super.prototype;
        Foo.prototype = new f();
        //等同于 Foo.prototype = Object.create(Super.prototype);
        
        var foo1 = new Foo(1,2);

Résumé :

L'héritage réalise principalement la réutilisation des méthodes et des attributs de la classe parent par les sous-classes.

Les propriétés de référence de l'objet prototype sont partagées par toutes les instances, nous voulons donc éviter d'hériter des propriétés du prototype.

Foo.prototype.constructor = Foo
Vous pouvez hériter des attributs et des méthodes du constructeur de classe parent via la fonction d'appel dans le constructeur, mais l'instance instanciée de cette manière stockera les méthodes de classe parent plusieurs fois, affectant les performances.

Grâce à l'héritage combiné, nous utilisons les propriétés d'héritage d'appel et la méthode d'héritage du prototype pour résoudre les deux problèmes ci-dessus. Cependant, l'objet instancié de cette manière stockera deux copies des propriétés dans le constructeur de la classe parent.

Utiliser le prototype de la classe parent pour construire un nouvel objet comme prototype de la sous-classe résout le problème du stockage multiple, donc l'héritage de combinaison parasite final est la meilleure méthode d'héritage. Son inconvénient est qu'il est plus. pénible à écrire.

3.3.6 Implémentation de l'héritage dans le code source du nœud

Ce qui précède est un exemple d'héritage de combinaison parasite.

1. Héritez des propriétés du constructeur Stream en appelant le constructeur OutgoingMessage.

2. Appelez la méthode hérite pour hériter des propriétés du prototype Stream.

3. Fonction qui étend le propre prototype d’OutgoingMessage.

function inherits(ctor, superCtor) {
  ctor.super_ = superCtor;
  ctor.prototype = Object.create(superCtor.prototype, {
    constructor: {
      value: ctor,
      enumerable: false,
      writable: true,
      configurable: true
    }
  });
}; 

function Stream(){
    //...
}

function OutgoingMessage() {
  Stream.call(this);
  //...
}

inherits(OutgoingMessage, Stream);

OutgoingMessage.prototype.setTimeout = ...
La méthode Object.create est utilisée dans la méthode hérite. La fonction de cette méthode est de créer un nouvel objet via l'objet prototype et les attributs spécifiés.

Cette méthode fait en fait le travail dans notre héritage de combinaison parasite ci-dessus

Les paramètres suivants servent à ajouter des attributs à l'objet prototype, des attributs facultatifs (non obligatoires) ), c'est-à-dire s'utiliser comme constructeur d'un objet nouvellement créé.

3.4 Comment implémenter l'héritage es6

ctor.prototype=Object.create(superCtor.prototype,{.....});
Référez-vous à mon article : https://segmentfault.com/a/11...

3.5 描述new一个对象的过程

  1. 创建一个对象

  2. {}._proto_ = 构造函数.prototype

  3. this指向这个对象

  4. 执行代码即对this赋值

  5. 返回this

3.6 zepto及其他源码中如何使用原型链

var Zepto = (function(){

    var $,zepto = {}
    
    // ...省略N行代码...
    
    $ = function(selector, context){
        return zepto.init(selector, context)
    }

    zepto.init = function(selector, context) {
        var dom
        
        // 针对参数情况,分别对dom赋值
        
        // 最终调用 zepto.Z 返回的数据
        return zepto.Z(dom, selector)
    }    

   fnction Z(dom, selector) {
      var i, len = dom ? dom.length : 0
     for (i = 0; i < len; i++) this[i] = dom[i]
      this.length = len
      this.selector = selector || ''
    }

   zepto.Z = function(dom, selector) {
     return new Z(dom, selector)
   }
  
    $.fn = {
        // 里面有若干个工具函数
    }
      
  
    zepto.Z.prototype = Z.prototype = $.fn
  
    
    // ...省略N行代码...
    
    return $
})()

window.Zepto = Zepto
window.$ === undefined && (window.$ = Zepto)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer