2009-06-21 8 views
2

J'ai plusieurs méthodes que j'ai besoin d'envelopper dans de nouvelles méthodes essentiellement de la même manière. Ma première solution ne fonctionne pas, et je comprends pourquoi, mais je ne sais pas s'il existe une solution simple à ce problème ou si cela ne peut pas être fait de la façon dont je veux le faire.Comment est-ce que je peux remplacer (enrouler) des méthodes dans de nouvelles méthodes par programme?

Voici un exemple. J'ai des objets a-c qui ont une méthode onClick. J'ai besoin d'exécuter du code avant les méthodes onClick. J'ai essayé les éléments suivants:

// objects a-c 
a = {onClick : function() { console.log('a'); }}; 
b = {onClick : function() { console.log('b'); }}; 
c = {onClick : function() { console.log('c'); }}; 

// first try 
var arr = [a, b, c] 
for (var i = 0; i < arr.length; i++) { 
    var oldOnClick = arr[i].onClick; 
    arr[i].onClick = function() { 
     // new code here 
     oldOnClick(); 
    } 
} 

// outputs 'c' 
// what i want is to maintain a reference to the original method 
// so in this case, execute my new code and output 'a' 
a.onClick(); 

Cela ne fonctionne pas parce que quand la nouvelle méthode est appelée, oldOnClick pointera à la méthode de la dernière itération et non la méthode à quand il a été affecté.

Existe-t-il une solution simple que je néglige?

Répondre

3

Qu'est-ce que vous avez besoin est fermeture:

for(var i=0, l=arr.length; i<l; i++){ 
(function(i){ 
    var oldOnclick = arr[i].onClick; 
    //etc. 
})(i); 
} 
+0

ahh .. oui b/c qui va s'exécuter immédiatement. Merci, je pensais qu'il y avait une solution simple. :) –

+0

+1 pour utilisation de fermeture – dfa

1

règles contraignantes Javascript sont assez bizarre. Vraiment, javascript est assez étrange.

Je ne sais pas que j'appellerais cela le façon de le réparer, mais en introduisant une sous-fonction, vous pouvez introduire une autre liaison et ainsi résoudre ce problème particulier.

Votre (modifié pour le piratage Chrome rapide y) Code devient:

a = {onClick : function() { alert('a'); }}; 
b = {onClick : function() { alert('b'); }}; 
c = {onClick : function() { alert('c'); }}; 

var arr = [a, b, c] 
for (var i = 0; i < arr.length; i++) { 
    var oldOnClick = arr[i].onClick; 
    arr[i].onClick = bind(oldOnClick); 
} 

a.onClick(); 
b.onClick(); 
c.onClick(); 

function bind(oldFunc) 
{ 
    return function() { 
     //New Code 
     oldFunc(); 
    } 
} 

Le code ci-dessus vomit trois alertes: a, b, c. Tout ce qui remplace '// Nouveau code' sera exécuté au bon moment.

1

avez-vous essayé avec du framwork AOP pour Javascript?

par exemple en utilisant le plugin jQuery AOP:

jQuery.aop.before({target: String, method: 'replace'}, 
    function(regex, newString) { 
    alert("About to replace string '" + this + "' with '" + newString + 
      "' using regEx '" + regex + "'"); 
    } 
); 

vérifier aussi here.

+0

merci. J'ai peut-être besoin d'un cadre AOP à un moment donné. –

0
var a = {onClick : function() { console.log('a'); }}; 
var b = {onClick : function() { console.log('b'); }}; 
var c = {onClick : function() { console.log('c'); }}; 

var arr = [a, b, c]; 
for (var i = 0; i < arr.length; i++) { 
    var oldOnClick = arr[i].onClick; 
    arr[i].onClick = wrapHandler(oldOnClick); 
} 

function wrapHandler(handler) { 
    return function() { 
     console.log("New stuff"); 
     handler(); 
    } 
} 

a.onClick(); // outputs "New stuff" then "a" 
b.onClick(); // outputs "New stuff" then "b" 
b.onClick(); // outputs "New stuff" then "c" 
Questions connexes