Maison  >  Article  >  interface Web  >  Discutez de la fonction bind() en javascript

Discutez de la fonction bind() en javascript

coldplay.xixi
coldplay.xixiavant
2020-06-15 16:25:002033parcourir

Discutez de la fonction bind() en javascriptComprendre la fonction bind() en javascript

Partager :

La méthode bind() créera une nouvelle fonction , Lorsque cette nouvelle fonction est appelée, sa valeur this est le premier paramètre passé à bind(), et ses paramètres sont les autres paramètres de bind() et ses paramètres d'origine.

La syntaxe est la suivante :

fun.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg Lorsque la fonction liée est appelée, ce paramètre sera utilisé comme pointeur this de la fonction d'origine lors de son exécution. Ce paramètre n'a aucun effet lors de l'appel de la fonction liée à l'aide de l'opérateur new.

arg1, arg2, … (facultatif) Lorsque la fonction liée est appelée, ces paramètres ainsi que les paramètres de la fonction liée elle-même seront utilisés dans l'ordre comme paramètres de la fonction d'origine lors de son exécution.

Paramètres

Le premier paramètre de bind sera utilisé comme ce pointeur lorsque la fonction d'origine est en cours d'exécution, pas grand chose à dire et le deuxième paramètre de départ est facultatif, lorsque la fonction liée est appelée, ces paramètres ainsi que les paramètres de la fonction liée elle-même seront utilisés comme paramètres de la fonction d'origine lors de l'exécution dans l'ordre. Comment comprendre ? La fonction

function fn(a, b, c) {
  return a + b + c;
}
var _fn = fn.bind(null, 10);
var ans = _fn(20, 30); // 60

fn nécessite trois paramètres. La fonction _fn utilise 10 comme premier paramètre par défaut, vous n'avez donc besoin de transmettre que deux paramètres. Si vous transmettez accidentellement trois paramètres, ne vous inquiétez pas. les deux premiers seront pris.

function fn(a, b, c) {
  return a + b + c;
}
var _fn = fn.bind(null, 10);
var ans = _fn(20, 30, 40); // 60

A quoi ça sert ? Si les premiers paramètres de certaines fonctions ont été « par défaut », nous pouvons utiliser bind pour renvoyer une nouvelle fonction. En d’autres termes, bind() permet à une fonction d’avoir des paramètres initiaux prédéfinis. Ces arguments (le cas échéant) suivent ceci comme deuxième argument de bind(). Ils sont ensuite insérés au début de la liste d'arguments de la fonction cible, et les arguments passés à la fonction liée les suivent.

function list() {
  return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
// Create a function with a preset leading argument
var leadingThirtysevenList = list.bind(undefined, 37);
var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]

new

Le résultat renvoyé par bind est toujours une fonction Si c'est une fonction, elle peut être appelée par l'opérateur new. La spécification indique très clairement que lorsque l'opérateur new est utilisé pour appeler une fonction liée, le premier paramètre de bind n'est pas valide.

function Person(name, age) {
  this.name = name;
  this.age = age;
}
var _Person = Person.bind({});
var p = new _Person('hanzichi', 30); // Person {name: "hanzichi", age: 30}

Généralement, nous ne l'utilisons pas de cette façon, mais si vous souhaitez écrire un polyfill de liaison (http://caniuse.com/#search=bind), vous devez toujours envisager d'utiliser new pour appeler il.

Nous pouvons également définir des valeurs par défaut (voir la section précédente), et les paramètres initialement fournis seront toujours ajoutés au début de l'appel du constructeur.

function Person(name, age) {
  this.name = name;
  this.age = age;
}
var _Person = Person.bind(null, 'hanzichi');
var p = new _Person(30); // Person {name: "hanzichi", age: 30}

Avec setTimeout

Quand est-il facile de perdre ce pointeur ? Eh bien, setTimeout est une scène, et il est facile de la pointer vers la fenêtre. Bien sûr, la même chose est vraie pour setInterval. Lorsque vous utilisez les méthodes d'un objet, qui nécessitent que this fasse référence à l'objet, vous devrez peut-être le lier explicitement à la fonction de rappel afin de continuer à utiliser l'objet.

var canvas = {
  render: function() {
    this.update();
    this.draw();
  },
  update: function() {
    // ...
  },
  draw: function() {
    // ...
  }
};
window.setInterval(canvas.render, 1000 / 60);

Nous rencontrons souvent des problèmes similaires lorsque nous utilisons Canvas pour écrire des effets spéciaux ou créer des jeux. Il y a un problème avec le code ci-dessus. Dans la méthode de rendu, il pointe en fait vers la fenêtre ! Nous pouvons utiliser bind pour lier explicitement cela à la fonction de rappel afin que nous puissions continuer à utiliser l'objet.

window.setInterval(canvas.render.bind(canvas), 1000);

Une situation similaire est la surveillance des événements de dom. Si vous ne faites pas attention, cela peut être pointé vers l'élément dom. Vous pouvez vous référer à cette partie du code écrit lorsque vous travaillez sur bigrender avant https://github.com/hanzichi/hanzichi.github.io/blob/master/2016/bigrender/js/bigrender.js#L179-L184.

astuce

bind peut aussi faire des choses intéressantes.

De manière générale, pour convertir un objet de type tableau en tableau, nous utilisons slice (non pris en charge par ie9-). Référence #14

var slice = Array.prototype.slice;
// slice.apply(arguments);
// slice(arguments, 1);
bind 能让调用变的更加简单。
// same as "slice" in the previous example
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);
// ...
slice(arguments);
// slice(arguments, 1);

Pour un autre exemple similaire, par exemple, si l'on veut ajouter des événements à plusieurs nœuds, bien sûr il n'y a aucun problème avec la boucle for On peut aussi "plagier" la méthode forEach :

Array.prototype.forEach.call(document.querySelectorAll('input[type="button"]'), function(el){
  el.addEventListener('click', fn);
});

De plus, nous pouvons utiliser bind pour mieux encapsuler la fonction :

var unboundForEach = Array.prototype.forEach
  , forEach = Function.prototype.call.bind(unboundForEach);
forEach(document.querySelectorAll('input[type="button"]'), function (el) {
  el.addEventListener('click', fn);
});

De même, nous pouvons changer x.y(z) sous la forme y(x,z) :

var obj = {
  num: 10,
  getCount: function() {
    return this.num;
  }
};
var unboundBind = Function.prototype.bind
  , bind = Function.prototype.call.bind(unboundBind);
var getCount = bind(obj.getCount, obj);
console.log(getCount());  // 10

Donnez un autre exemple. Imprimer 1 à 5 sur la console chaque seconde semble être un problème classique lors de l'examen des fermetures.

for(var i = 1; i <= 5; i++) {
  !function(i) {
    setTimeout(function() {
      console.log(i);
    }, i * 1000);
  }(i);
}

Vous pouvez utiliser let sous ES6 :

for(let i = 1; i <= 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, i * 1000);
}

Vous pouvez également utiliser bind pour améliorer instantanément vos performances :

for(var i = 1; i <= 5; i++) {
  setTimeout(console.log.bind(console, i), i * 1000);
}

Tutoriel recommandé : "Tutoriel de base js

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