Maison  >  Article  >  interface Web  >  Explication détaillée des appels implicites en javascript

Explication détaillée des appels implicites en javascript

小云云
小云云original
2018-02-10 14:32:042083parcourir

L'appel dit implicite signifie simplement appeler automatiquement certaines méthodes, et ces méthodes peuvent être modifiées en externe comme des hooks, modifiant ainsi le comportement établi.

Ci-dessous, je vais énumérer quelques appels implicites que j'ai vus récemment. Les exemples sont justes. Bienvenue pour ajouter

Conversion de type de données en Sting et valueOf

var obj = {
      a: 1,
      toString: function () {
        console.log('toString')
        return '2'
      },
      valueOf: function () {
        console.log('valueOf')
        return 3
      }
    }
    console.log(obj == '2'); //依次输出 'valueOf' false
    console.log(String(obj));//依次输出 'toString' '2'
var obj = {
      a: 1,
      toString: function () {
        console.log('toString')
        return '2'
      },
      valueOf: function () {
        console.log('valueOf')
        return {} //修改为对象
      }
    }
    console.log(obj == '2'); //依次输出 'valueOf' 'toString' true
    console.log(Number(obj));//依次输出 'valueOf' 'toString' 2
Dans le fonctionnement de l'opérateur d'égalité, l'objet appellera d'abord valueOf Si la valeur renvoyée est un objet, il appellera toSting, sauf null, puis utilisera la valeur renvoyée pour comparaison. équivaut à 3 == '2' renvoie false. Le deuxième exemple renvoie un objet car valueOf est exécuté, puis toString est exécuté Enfin, il équivaut à '2' == '2' et renvoie true

In. les méthodes Number et String, Number sera d'abord appelée valueOf, puis appellera toString. L'inverse est vrai dans la méthode String.
En plus des deux exemples ci-dessus, la conversion de type de données existe également dans diverses autres opérations, telles que les opérations numériques. Lorsque des types référence sont impliqués, la méthode valueOf ou toString sera appelée tant que l'objet est un objet. il héritera de ces deux méthodes, nous pouvons re-redéfinir ces deux méthodes pour affecter le comportement de la conversion du type de données

handleEvent dans l'événement DOM2

var eventObj = {
      a: 1,
      handleEvent: function (e) {
        console.log(this, e);//返回 eventObj 和 事件对象
        alert(this.a)
      }
    }
    document.addEventListener('click', eventObj)
Vous avez bien lu, le deuxième paramètre de addEventListener est en plus de la fonction Il peut également s'agir d'un objet. Une fois l'événement déclenché, la méthode handleEvent de l'objet sera exécutée lorsque la méthode est exécutée, cela pointe vers eventObj. transmettre à l'objet eventObj

Objet JSON toJSON

var Obj = {
      a: 10,
      toJSON: function () {
        return {
          a: 1,
          b: function () {
          },
          c: NaN,
          d: -Infinity,
          e: Infinity,
          f: /\d/,
          g: new Error(),
          h: new Date(),
          i: undefined,
         
        }
      }
    }
    console.log(JSON.stringify(Obj));
    //{"a":1,"c":null,"d":null,"e":null,"f":{},"g":{},"h":"2018-02-09T19:29:13.828Z"}
Si l'objet transmis par la méthode stringify de JSON a une méthode toJSON, alors l'objet exécuté par cette méthode sera converti en objet renvoyé après l'exécution de toJSON. Une chose à noter est que, comme dans le code suivant

 var Obj1 = {
      a: 10,
      toJSON: function () {
        console.log(this === Obj1);//true
        return this
      }
    }
    console.log(JSON.stringify(Obj1));//{"a":10}
 var Obj2 = {
      a: 10,
      toJSON: function () {
        console.log(this === Obj2);//true
        return {
          a: this
        }
      }
    }
    console.log(JSON.stringify(Obj2));//报错 Maximum call stack size exceeded
Si selon la déclaration ci-dessus, il est évident que l'erreur est celle à laquelle nous nous attendions, mais lors du renvoi direct de ceci, aucune erreur n'est signalée. Vous pourriez aussi bien faire une supposition audacieuse sur la comparaison interne entre l'objet renvoyé par toJSON et l'objet d'origine. S'ils sont égaux, utilisez directement then

.

de l'objet d'origine

var obj = {
      then: function (resolve, reject) {
        setTimeout(function () {
          resolve(1000);
        }, 1000)
      }
    }
    Promise.resolve(obj).then(function (data) {
      console.log(data);// 延迟1秒左右输出 1000
    })
objet promis. Lorsque la méthode Promise.resolve passe l'objet, si la méthode then existe, la méthode then sera exécutée immédiatement, ce qui équivaut à remplacer la méthode Put. dans la nouvelle Promise, en plus de Promise.resolve ayant ce comportement, Promise.all a également ce comportement

 var timePromise = function (time) {
       return new Promise(function (resolve) {
         setTimeout(function () {
           resolve(time);
         }, time)
       })
     }
     var timePromise1 = timePromise(1000);
     var timePromise2 = timePromise(2000);
     var timePromise3 = timePromise(3000);
     Array.prototype.then = function (resolve) {
         setTimeout(function () {
           resolve(4000);
         }, 4000)
       }
     Promise.all([timePromise1, timePromise2, timePromise3]).then(function (time) {
       console.log(time);// 等待4秒左右输出 4000
     })
Vous pouvez voir les accesseurs d'attribut d'objet obtenir et définir

var obj = {
       _age: 100,
       get age() {
         return this._age < 18 ? this._age : 18;
       },
       set age(value) {
         this._age = value;
         console.log(`年龄设置为${value}岁`);
       }
     }
     obj.age = 1000; //年龄设置为1000岁
     obj.age = 200; //年龄设置为200岁
     console.log(obj.age);// 18
     obj.age = 2; ////年龄设置为2岁
     console.log(obj.age); // 2
Quel que soit l'âge défini, mon âge est de 18 ans ou moins. Lors de l'accès aux attributs, la fonction get set correspondante de l'attribut d'objet est en fait appelée. En plus de la méthode d'écriture ci-dessus, il existe également la méthode d'écriture suivante <.>

Maintenant, la valeur de l'entrée et la valeur innerHTML de la valeur d'attribut de obj.age sont liées ensemble
  var input = document.createElement('input');
    var span = document.createElement('span');
    document.body.appendChild(input);
    document.body.appendChild(span);
    var obj = {
      _age:''
    }
    var obj = Object.defineProperty(obj, 'age', {
      get: function () {
        return this._age;
      },
      set: function (value) {
        this._age = value;
        input.value = value;
        span.innerHTML = value;
      }
    });
    input.onkeyup = function (e) {
      if (e.keyCode === 37 || e.keyCode === 39) {
        return;
      }
      obj.age = this.value
    }

Interface de l'itérateur Symbol.iterator

Vous pouvez tout voir. Appeler l'opérateur spread ou utiliser une boucle for...of pour parcourir un objet appellera l'interface de traversée de l'objet, telle que Array, String, Map, Set, TypedArray et certains objets de type tableau tels que les arguments et NodeList a nativement une interface traverseur.Les objets ordinaires ne déploient pas cette interface.Si vous souhaitez que l'objet puisse utiliser l'opérateur spread ou la boucle for...of, vous pouvez ajouter cette méthode à l'objet, ou vous pouvez réécrire le. méthode sur l’objet d’origine avec l’interface pour modifier son comportement.
 var arr = [ 1, 2 , 3];
    arr[Symbol.iterator] = function () {
      const self = this;
      let index = 0;
      return {
        next () {
          if(index < self.length) {
            return {
              value: self[index] ** self[index++],
              done: false
            }
          } else {
            return {
              value: undefined,
              done: true
            }
          }
        }
      }
    }
    console.log([...arr, 4]);//返回 [1, 4, 27, 4]
    for(let value of arr) {
      console.log(value); //依次返回 1 4 27
    }

Recommandations associées :

php, comment une sous-classe appelle implicitement la méthode de la classe parent

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn