21 votes

question sur la fonction bind de mozilla

J'ai une question sur une implémentation de la fonction bind que j'ai trouvée sur le site de Mozilla. Pour l'essentiel, cela me semble logique, mais je n'arrive pas à comprendre à quoi sert cette vérification...

this instanceof nop ? this : ( obj || {} ) 

dans la fonction bind. Il est évident qu'il vérifie si 'this' est la fonction vide, mais pourquoi auriez-vous besoin de lier la fonction vide ? J'ai essayé dans firebug, cela fonctionne, mais quel est l'intérêt ? J'essaie juste d'améliorer mes connaissances en javascript et toute aide serait appréciée.

if ( !Function.prototype.bind ) {

  Function.prototype.bind = function( obj ) {

    var slice = [].slice,
    args = slice.call(arguments, 1), 
    self = this, 
    nop = function () {}, 
    bound = function () {
      return self.apply( this instanceof nop ? this : ( obj || {} ), 
                          args.concat( slice.call(arguments) ) );    
    };

    nop.prototype = self.prototype;

    bound.prototype = new nop();

    return bound;
  };
}

31voto

Matthew Crumley Points 47284

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.

1voto

Willy Banús Points 11

Peut-être que je me trompe complètement mais :

Pourquoi ne pas utiliser uniquement le prototype de la première fonction qui appelle bind pour l'utiliser comme condition, au lieu de créer une nouvelle fonction comme nop(), cela fonctionne pour moi.

Il est peut-être important de créer la fonction nop() pour une raison que je ne comprends pas encore (je suis nouveau en JavaScript).

Function.prototype.bind = function( obj ) {

var slice = [].slice,
args = slice.call(arguments, 1), 
self = this,  
bound = function () {
  return self.apply( this instanceof self ? this : ( obj || {} ), 
                      args.concat( slice.call(arguments) ) );    
};

bound.prototype = self.prototype;

return bound;
};

0voto

morgar Points 1706

Je pense que c'est une notation courte pour (typeof obj != "undefined") ? obj : {}

C'est-à-dire que si obj n'est pas indéfini, retourne obj sinon, retour d'un objet vide ({} est un objet vide).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X