2010-05-06 4 views
1

En Javascript, si nous aliasing une fonction (ou, attribuer une « référence à une fonction » à une autre variable), comme dans:En Javascript, est-il vrai que l'alias de fonction fonctionne tant que la fonction en cours d'alias ne touche pas "ceci"?

f = g; 
f = obj.display; 
obj.f = foo; 

toutes les 3 lignes ci-dessus, ils fonctionneront aussi longtemps que la fonction/méthode sur le côté droit ne touche pas this? Puisque nous passons dans tous les arguments, la seule façon dont il peut gâcher est quand la fonction/méthode sur la droite utilise this? En fait, la ligne 1 est probablement correcte si g est également une propriété de window? Si g fait référence à obj.display, alors le même problème est là.

Dans la ligne 2, quand obj.display touche this, il est de signifier la obj, mais quand f est invoquée, la this est window, donc ils sont différents.

Dans la ligne 3, il est le même: quand f est invoqué à l'intérieur du Code de obj, le this est obj, tout en foo susceptibles d'utiliser this pour désigner window si elle était une propriété de window. (fonction globale).

Ainsi la ligne 2 peut être écrit comme

f = function() { obj.display.apply(obj, arguments) } 

et la ligne 3:

obj.f = function() { foo.apply(window, arguments) } 

Est-ce la bonne méthode? Et y a-t-il d'autres méthodes à part cela?

+0

Cela me fait penser à M.C. Marteau – hobodave

+0

je sais. J'essayais de ne pas le mentionner dans la question initiale. –

+0

Félicitations, vous venez de découvrir la raison pour laquelle je déteste la programmation orientée objet en Javascript. En raison de l'absence de fonctions liées, vous devez toujours faire attention au contexte et (donc) à ce que cela indique. Maintenant vous pouvez passer à un vrai langage OOP (désolé :). – wump

Répondre

3

Fondamentalement oui, cependant, dans les fonctions JavaScript sont des objets de première classe, donc il n'y a pas vraiment d'aliasing. Ce que vous faites est d'assigner la valeur d'une variable à une autre variable, et dans ce cas la valeur est juste une fonction.

La magie cette variable cependant est un peu différente. En JavaScript, les méthodes ne sont pas liées à une classe ou à un objet, comme dans la plupart des autres langages. Lorsque vous appelez une méthode ce est défini par l'opérateur point, ou par le appliquer ou appel méthodes. Il fonctionne comme ceci:

var i = 1; 
var f = function() { alert(this.i); } 
f(); // in a browser, alerts 1, because this will be window if it isn't anything else. 

var obj = { i: 10 }; 
obj.g = f; 
obj.g(); // alerts 10, because the dot binds this to obj 

var other_obj = { i: 23 }; 
f.apply(g); // alerts 23, because now apply binds this to other_obj 

Vous pouvez lier des méthodes à des objets en utilisant des fermetures:

var f = function() { alert(this.i); } 
var obj = { i: 10 }; 

obj.m = function() { f.apply(obj); } 
obj.m(); // alerts 10 

var g = obj.m; 
g(); // alerts 10, because now the closure is called, which binds this correctly. 
1

La signification de "ceci" et des étendues comme ils s'appliquent aux fonctions, en particulier les rappels, semble être un "gotcha" JavaScript classique.

Dojo dispose d'une méthode hitch() qui résout le problème, ce qui permet d'obtenir le contexte attendu pour les méthodes de rappel. Je suppose qu'un développeur non-dojo pourrait jeter un coup d'œil au code Dojo hitch() pour emprunter les idées.

Ce article explique certains aspects du problème «this» et comment utiliser l'attelage Dojo().

1

« ce » fait référence uniquement à l'objet à l'intérieur de votre fonction si vous invoquez un objet de cette façon:

obj.f(); 

Cela ne marchera jamais, comme javascript manque de soutien pour « fonctions liées » (n » t vous rappeler quel objet une méthode appartient à):

var x = context.lineTo; 
x(10,10); 

lineTo va se confondre « ce » pointe maintenant à la fenêtre ou de l'objet de la fonction actuelle au lieu de son contexte attendu. Donc, en effet, vous devez toujours appliquer dans votre cas.

Questions connexes