Cela vous permet d'appeler la fonction liée comme un constructeur sans être lié à l'objet original. En d'autres termes, la fonction "liée" fonctionnera toujours comme la version originale, non liée, si vous l'appelez avec la commande new
.
Voici un exemple :
var obj = {};
function foo(x) {
this.answer = x;
}
var bar = foo.bind(obj); // "always" use obj for "this"
bar(42);
console.log(obj.answer); // 42
var other = new bar(1); // Call bar as a constructor
console.log(obj.answer); // Still 42
console.log(other.answer); // 1
Comment cela fonctionne
Pour simplifier l'explication, voici une version simplifiée du code qui lie seulement this
et ne gère pas les arguments ou un paramètre obj manquant :
Function.prototype.bind = function( obj ) {
var self = this,
nop = function () {},
bound = function () {
return self.apply( this instanceof nop ? this : obj, arguments );
};
nop.prototype = self.prototype;
bound.prototype = new nop();
return bound;
};
La fonction qui est retournée par Function.prototype.bind
se comporte différemment selon que vous l'utilisez comme une fonction ou comme un constructeur (cf. Section 15.3.4.5.1 y 15.3.4.5.2 de la spécification de langage ECMAScript 5). La principale différence est qu'il ignore le paramètre "bound this" lorsqu'il est appelé en tant que constructeur (car à l'intérieur d'un constructeur, this
doit être l'objet nouvellement créé). Ainsi, le bound
a besoin d'un moyen de déterminer comment elle est appelée. Par exemple, bound(123)
vs. new bound(123)
et mettre this
en conséquence.
C'est là que le nop
fonction entre en jeu. Elle agit essentiellement comme une "classe" intermédiaire de sorte que bound
étend nop
qui prolonge self
(qui est la fonction bind()
a été appelé). Cette partie est mise en place ici :
nop.prototype = self.prototype;
bound.prototype = new nop();
Lorsque vous appelez la fonction bound, elle renvoie cette expression :
self.apply( this instanceof nop ? this : obj, arguments ) )
this instanceof nop
fonctionne en suivant la chaîne des prototypes pour déterminer l'éventuel prototype de this
est égal à nop.prototype
. En fixant nop.prototype = self.prototype
y bound.prototype = new nop()
tout objet créé avec new bound()
sera créé avec le prototype original de self
via bound.prototype
. Donc à l'intérieur de l'appel de fonction, this instanceof nop
(c'est-à-dire que Object.getPrototypeOf(nop) == nop.prototype) est true
y self
est appelé avec this
(l'objet nouvellement créé).
Dans un appel de fonction normal, 'bound()' (sans new
), this instanceof nop
serait faux, donc obj
est transmis en tant que this
ce qui correspond à ce que l'on attend d'une fonction liée.
La raison de l'utilisation de la fonction intermédiaire est d'éviter d'appeler la fonction originale (dans la ligne bound.prototype = new nop();
), qui peuvent avoir des effets secondaires.