explication sur prototype.js code de fonction de liaison
-
30-09-2019 - |
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)));
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.