Les appels de fonction
Les fonctions sont juste un type d'Objet.
Tous les objets de Fonction ont appel et appliquer des méthodes d'exécuter la Fonction de l'objet qu'ils sont appelés sur.
Lorsqu'il est appelé, le premier argument de ces méthodes spécifie l'objet qui va être référencé par l' this
mot-clé lors de l'exécution de la Fonction - si c'est l' null
ou undefined
, l'objet global, window
, est utilisé pour l' this
.
Ainsi, l'appel d'une Fonction...
whereAmI = "window";
function foo()
{
return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}
...avec des parenthèses - foo()
- est équivalent à foo.call(undefined)
ou foo.apply(undefined)
, ce qui est effectivement le même que foo.call(window)
ou foo.apply(window)
.
>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"
Des arguments supplémentaires à l' call
sont passés comme arguments à l'appel de la fonction, tandis qu'un seul argument supplémentaire pour apply
pouvez spécifier les arguments de l'appel de fonction dans un Tableau comme objet.
Ainsi, foo(1, 2, 3)
est équivalent à foo.call(null, 1, 2, 3)
ou foo.apply(null, [1, 2, 3])
.
>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"
Si une fonction est une propriété d'un objet...
var obj =
{
whereAmI: "obj",
foo: foo
};
...l'accès à une référence à la Fonction via l'objet et de l'appeler avec des parenthèses - obj.foo()
- est équivalent à foo.call(obj)
ou foo.apply(obj)
.
Cependant, les fonctions de tenue comme des propriétés des objets ne sont pas "liés" à ces objets. Comme vous pouvez le voir dans la définition de l' obj
- dessus, car les Fonctions sont juste un type d'Objet, ils peuvent être référencés (et peut donc être transmis par référence à un appel de Fonction ou retourné par référence à partir d'un appel de Fonction). Lorsqu'une référence à une Fonction est passé, aucune information supplémentaire sur l'endroit où il était passé de est emporté avec elle, c'est pourquoi les cas suivants:
>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"
L'appel à notre Fonction de référence, baz
, n'est pas de fournir un contexte pour l'appel, donc c'est effectivement la même que baz.call(undefined)
, alors this
finit référencement window
. Si nous voulons baz
à savoir qu'il appartient à l' obj
, nous avons besoin de quelque manière que l'information lors de l' baz
est appelé, qui est l'endroit où le premier argument call
ou apply
et de fermetures entrent en jeu.
La portée des chaînes
function bind(func, context)
{
return function()
{
func.apply(context, arguments);
};
}
Lorsqu'une Fonction est exécuté, il crée un nouveau champ d'application et a une référence à un cadre englobant. Lorsque la fonction anonyme est créé dans l'exemple ci-dessus, il a une référence vers la portée, il a été créé, qui est - bind
s'portée. Ceci est connu comme une "fermeture".
[global scope (window)] - whereAmI, foo, obj, baz
|
[bind scope] - func, context
|
[anonymous scope]
Lorsque vous essayez d'accéder à une variable du champ d'application de la chaîne d'" est parcouru de trouver une variable avec le nom donné - si le champ ne contient pas la variable, vous regardez à la prochaine portée dans la chaîne, et ainsi de suite jusqu'à ce que vous atteindre une portée globale. Lorsque la fonction anonyme est retourné et bind
issue de l'exécution, la fonction anonyme a encore une référence à l' bind
s'étendue, bind
s'étendue de ne pas "s'en aller".
Compte tenu de tous les ci-dessus, vous devriez maintenant être en mesure de comprendre comment étendue fonctionne dans l'exemple suivant, et pourquoi la technique pour le passage d'une fonction autour de "pré-lié" avec une valeur particulière de l' this
il aura lorsqu'il est appelé œuvres:
>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"