2010-12-15 2 views
2

cette fermeture fonctionne:Puis-je utiliser y-combinator pour obtenir une référence d'objet pour cette fermeture?

var o = { 
    foo: 5 
}; 

o.handler = function(obj){ 
    return function() { 
     alert(obj.foo); 
    }; 
}(o); 

o.handler(); //alert('5') 

est-il possible de définir gestionnaire en ligne, peut-être quelque chose de semblable à une opération y combinateur?

var o = { 
    foo: 5, 
    handler: function(obj){ 
     return function() { 
      alert(obj.foo); 
     }; 
    }(o); //pointer to o? ----------------------------- 
}; 

par curiosité académique, je ne suis pas essayer de le faire dans le code de production

intro to the y-combinator

Répondre

1

Non, cela est impossible, car au moment de la définition de l'objet littéral, la variable o n'est pas définie et la référence this au moment de la définition ne fait pas référence à o.

Si vous utilisiez une référence temporaire à this dans la fonction externe et que vous la transmettiez à la fermeture, cela fonctionnerait, mais vous ne seriez pas en mesure de transmettre un objet pour obtenir la propriété foo sur.

var o = { 
    foo: 5, 
    handler:function(){ 
     var self = this; 
     return function() { 
      alert(self.foo); 
     }; 
    } 
}; 

var h = o.handler(); 
h(); 
+0

Il y a [toujours] un 'ceci' (juste pas le bon) –

+1

@pst Vous avez raison, dans ce cas, il ferait référence' window'. –

0

Vous pouvez simplement utiliser le mot-clé this ici:

var o = { 
    foo: 5, 
    handler: function() { 
     alert(this.foo); 
    } 
}; 

C'est beaucoup plus facile approche ... En fait, votre approche est même pas possible, car o n'est pas défini lorsque vous faites référence à il.

+1

Mais ceci n'est pas * strictement * le même que "this" peut différer si 'handler' est appelé sur un récepteur différent (ou, disons, passé comme un callback). –

1

Ceci n'est pas possible avec un objet littéral par lui-même, comme d'autres l'ont souligné. Cependant, le processus peut être emballé. Que ce soit ou non "ajoute quelque chose" est discutable. Ce n'est pas la même chose qu'un Y-Combinator (peut-être la moitié?), Car il n'essaie pas de donner un "nom récursif" (pour autant que je sache, Y-Combinators assument des fonctions et des fermetures de premier ordre). façon de simuler un tel).

function bindMany (dict, res) { 
    res = res || {} 
    for (var k in dict) { 
    if (dict.hasOwnProperty(k)) { 
     var v = dict[p] 
     res[k] = v instanceof Function ? v(res) : v 
    } 
    } 
    return res 
} 

var o = bindMany({ 
    foo: 5, 
    handler: function(obj){ 
    return function() { 
     alert(obj.foo) 
    } 
    } 
}) 

Non-testé, mais montre une approche qui pourrait prendre. Il y a des problèmes subtils avec ceci et une chaîne de prototype sur dict/res, le cas échéant - un exercice pour le lecteur.

Bonne codification.

Questions connexes