Question

De: http://ejohn.org/apps/learn/#2

Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

Quelqu'un peut-il me dire pourquoi le second retour est nécessaire (avant fn.apply)?

En outre, quelqu'un peut-il expliquer pourquoi args.concat est nécessaire? Pourquoi ne serait-il être réécrite comme:

fn.apply(object, args)

au lieu de

return fn.apply(object,
          args.concat(Array.prototype.slice.call(arguments)));
Était-ce utile?

La solution

Le second retour est nécessaire parce que sinon nous allons perdre toute valeur de retour de la fonction liée.

Vous pouvez déjà savoir, mais ne fait pas mal à mentionner. Si nous ne terminerons fn.apply dans une autre fonction, nous appelons directement la fonction fn qui est sous-optimale, car bind n'est censé définir le contexte d'exécution (ce qui devrait this se référer à l'intérieur de la fonction), et non l'invoquons .

méthodes Javascript peut être invoquée en appelant la méthode call ou apply sur eux. Voici un petit exemple:

function example() {
    alert("useless example");
}

example.apply() // or example.call(), alerts "useless example";

La fonction externe dans la liaison de prototype () est censé fonctionner comme un wrapper autour invisible la fonction liée. Ainsi, tous les arguments qui sont passés à l'emballage doivent être transmis à la fonction liée aussi bien, et il doit retourner une valeur que la fonction retourne liées, ce qui est la raison pour laquelle la déclaration de retour est là.

La raison de faire args.concat est à l'intérieur fn.apply différent et ce n'est pas en option. bind dans Prototype vous permet de préfixer arguments à la fonction liée.

args représente les arguments qui ont été adoptées lorsque nous avons appelé bind la fonction. arguments représente les arguments qui ont été adoptées lorsque nous avons appelé la fonction liée. Nous concaténer essentiellement deux tableaux là.

Dans l'exemple ci-dessus:

var obj = { x: 'prop x' };
var boundExample = example.bind(obj, 12, 23); // args => 12, 23
boundExample(36, 49); // arguments => 36, 49

// arguments that our example() function receives => 12, 23, 36, 49

Autres conseils

Ancien poste, mais une approche plus récente;)

Function.prototype.bind = function(){
    var fn = this, 
    context = arguments[0], 
    args = Array.prototype.slice.call(arguments, 1);
    return function(){
        return fn.apply(context, args.concat([].slice.call(arguments)));
    }
}

obj = {'abc':'x'};
var func = function() {
  console.log(arguments);
  alert(this.abc);
}
var x = func.bind(obj);

console.log(x(1,2,3));

Ceci est un très bon exemple pour expliquer. Lancez-le et vérifiez le journal de la console. Modifiez ensuite le code pour laisser de

[].slice.call(arguments)

Vous verrez que le console.log de l'exécution de x (1,2,3) ne montre pas les arguments plus. En effet, les arguments des objets est une variable locale dans toutes les fonctions. Cela peut sembler un peu déroutant, mais ce que cela signifie est essentiellement:

var x = func.bind(obj,1,2,3);

Renvoie cette fonction interne:

function() {
    return fn.apply(obj, [1,2,3].concat([].slice.call(arguments)));
}

Il est donc plus d'un modèle pour la fonction.

Lorsque vous exécutez maintenant comme:

x(4,5,6)

Ce sera RAN:

fn.apply(obj, [1,2,3].concat([].slice.call(arguments)))

avec des arguments particuliers object = {0: 4,1: 5,2: 6}, qui peut être converti en un tableau en utilisant le [] .slice.call où arguments est un objet local, qui est automatiquement assigné pendant la beeing invocation de la fonction.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top