Maison  >  Article  >  interface Web  >  Une brève analyse de l'utilisation et de la mise en œuvre de la méthode bind() dans les compétences Javascript_javascript

Une brève analyse de l'utilisation et de la mise en œuvre de la méthode bind() dans les compétences Javascript_javascript

WBOY
WBOYoriginal
2016-05-16 15:02:531279parcourir

Avant de discuter de la méthode bind(), examinons une question :

var altwrite = document.write
altwrite("bonjour");
//1. Quel est le problème avec le code ci-dessus
//2. Quelle est la bonne opération
//3.Comment implémenter la méthode bind()

Pour la question ci-dessus, la réponse n'est pas trop difficile. Le principal point de test est le problème signalé par ceci. La fonction altwrite() change le point de ceci en objet global ou window, ce qui entraîne une exception d'appel illégale pendant. exécution. La bonne solution est d'utiliser la méthode bind ():

altwrite.bind(document)("bonjour")
Bien sûr, vous pouvez également utiliser la méthode call() :

altwrite.call(document, "bonjour")
L'objectif de cet article est de discuter du troisième problème, l'implémentation de la méthode bind(). Avant de commencer à discuter de l'implémentation de bind(), jetons d'abord un coup d'œil à l'utilisation de la méthode bind() :

.

Fonction de liaison
L'utilisation la plus simple de bind() consiste à créer une fonction afin qu'elle ait la même valeur, quelle que soit la manière dont elle est appelée. Une erreur courante consiste à retirer la méthode de l'objet, puis à l'appeler, en espérant que cela pointe vers l'objet d'origine, comme dans l'exemple ci-dessus. Si aucun traitement particulier n’est effectué, l’objet original sera généralement perdu. L'utilisation de la méthode bind() peut résoudre ce problème à merveille :

this.num = 9; 
var mymodule = { 
 num: 81,
 getNum: function() { return this.num; }
};

module.getNum(); // 81

var getNum = module.getNum; 
getNum(); // 9, 因为在这个例子中,"this"指向全局对象

// 创建一个'this'绑定到module的函数
var boundGetNum = getNum.bind(module); 
boundGetNum(); // 81 

Fonctions partielles

Les fonctions partielles sont également appelées applications partielles. Voici une définition des fonctions partielles :

Une application partielle peut être décrite comme prenant une fonction qui accepte un certain nombre d'arguments, liant des valeurs à un ou plusieurs de ces arguments et renvoyant une nouvelle fonction qui n'accepte que les arguments restants non liés.

C'est une bonne fonctionnalité. En utilisant bind(), nous définissons les paramètres prédéfinis de la fonction, puis transmettons d'autres paramètres lors de l'appel :

function list() { 
 return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

// 预定义参数37
var leadingThirtysevenList = list.bind(undefined, 37);

var list2 = leadingThirtysevenList(); // [37] 
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3] 

Utiliser avec setTimeout

Généralement, celui de setTimeout() pointe vers la fenêtre ou l'objet global. Lorsque vous en avez besoin pour pointer vers une instance de classe lorsque vous utilisez une méthode de classe, vous pouvez utiliser bind() pour la lier à la fonction de rappel afin de gérer l'instance.

function Bloomer() { 
 this.petalCount = Math.ceil(Math.random() * 12) + 1;
}

// 1秒后调用declare函数
Bloomer.prototype.bloom = function() { 
 window.setTimeout(this.declare.bind(this), 1000);
};

Bloomer.prototype.declare = function() { 
 console.log('我有 ' + this.petalCount + ' 朵花瓣!');
};

Remarque : la méthode ci-dessus peut également être utilisée pour les fonctions de gestion d'événements et les méthodes setInterval

Fonction de liaison en tant que constructeur

Les fonctions liées conviennent également à l'utilisation de l'opérateur new pour construire des instances de la fonction cible. Lorsque vous utilisez une fonction liée pour construire une instance, notez : cela sera ignoré, mais les paramètres transmis seront toujours disponibles.

function Point(x, y) { 
 this.x = x;
 this.y = y;
}

Point.prototype.toString = function() { 
 return this.x + ',' + this.y; 
};

var p = new Point(1, 2); 
p.toString(); // '1,2'


var emptyObj = {}; 
var YAxisPoint = Point.bind(emptyObj, 0/*x*/); 
// 实现中的例子不支持,
// 原生bind支持:
var YAxisPoint = Point.bind(null, 0/*x*/);

var axisPoint = new YAxisPoint(5); 
axisPoint.toString(); // '0,5'

axisPoint instanceof Point; // true 
axisPoint instanceof YAxisPoint; // true 
new Point(17, 42) instanceof YAxisPoint; // true 

Dans l'exemple ci-dessus, Point et YAxisPoint partagent des prototypes, c'est donc vrai lors de l'utilisation de l'opérateur instanceof.

Raccourci

bind() peut également créer des raccourcis pour les fonctions qui nécessitent une valeur spécifique.

Par exemple, si vous souhaitez convertir un objet de type tableau en un véritable tableau, les exemples possibles sont les suivants :

var slice = Array.prototype.slice;

// ...

slice.call(arguments); 

Si vous utilisez bind(), la situation devient plus simple :

var unboundSlice = Array.prototype.slice; 
var slice = Function.prototype.call.bind(unboundSlice);

// ...

slice(arguments); 

Réussite

Il ressort des sections ci-dessus que bind() a de nombreux scénarios d'utilisation, mais la fonction bind() n'a été ajoutée que dans la cinquième édition d'ECMA-262 ; elle peut ne pas fonctionner sur tous les navigateurs. Cela nous oblige à implémenter nous-mêmes la fonction bind().

Tout d'abord, nous pouvons simplement implémenter la méthode bind() en spécifiant une portée pour la fonction cible :

Function.prototype.bind = function(context){ 
 self = this; //保存this,即调用bind方法的目标函数
 return function(){
   return self.apply(context,arguments);
 };
};

En tenant compte du currying des fonctions, nous pouvons construire un bind() plus robuste :

Function.prototype.bind = function(context){ 
 var args = Array.prototype.slice.call(arguments, 1),
 self = this;
 return function(){
   var innerArgs = Array.prototype.slice.call(arguments);
   var finalArgs = args.concat(innerArgs);
   return self.apply(context,finalArgs);
 };
};

Cette fois, la méthode bind() peut lier des objets et prend également en charge la transmission de paramètres lors de la liaison.

En continu, les fonctions Javascript peuvent également être utilisées comme constructeurs, donc lorsque la fonction liée est appelée de cette manière, la situation est plus subtile et nécessite le transfert de la chaîne de prototypes :

Function.prototype.bind = function(context){ 
 var args = Array.prototype.slice(arguments, 1),
 F = function(){},
 self = this,
 bound = function(){
   var innerArgs = Array.prototype.slice.call(arguments);
   var finalArgs = args.concat(innerArgs);
   return self.apply((this instanceof F ? this : context), finalArgs);
 };

 F.prototype = self.prototype;
 bound.prototype = new F();
 return bound;
};

Il s'agit de l'implémentation de bind() dans le livre "JavaScript Web Application" : en mettant en place un constructeur de transit F, la fonction liée et la fonction qui appelle bind() sont sur la même chaîne prototype, et la nouvelle opération L'opérateur utilisé appelle la fonction liée, et l'objet renvoyé peut également utiliser instanceof normalement, il s'agit donc de l'implémentation la plus rigoureuse de bind().

Afin de prendre en charge la fonction bind() dans le navigateur, il vous suffit de modifier légèrement la fonction ci-dessus :

Function.prototype.bind = function (oThis) { 
  if (typeof this !== "function") {
   throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
  }

  var aArgs = Array.prototype.slice.call(arguments, 1), 
    fToBind = this, 
    fNOP = function () {},
    fBound = function () {
     return fToBind.apply(
       this instanceof fNOP && oThis ? this : oThis || window,
       aArgs.concat(Array.prototype.slice.call(arguments))
     );
    };

  fNOP.prototype = this.prototype;
  fBound.prototype = new fNOP();

  return fBound;
 };

La brève analyse ci-dessus de l'utilisation et de la mise en œuvre de la méthode bind() en Javascript est tout le contenu partagé par l'éditeur. J'espère qu'elle pourra vous donner une référence, et j'espère que vous soutiendrez Script Home.

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