Как программно заменить (обернуть) методы в новых методах? - PullRequest
2 голосов
/ 21 июня 2009

У меня есть несколько методов, которые мне нужно обернуть в новые методы в основном таким же образом. Мое первое решение не работает, и я понимаю, почему, но я не знаю, есть ли простое решение этой проблемы или его нельзя сделать так, как я хочу.

Вот пример. У меня есть объекты a-c, которые имеют метод onClick. Мне нужно выполнить некоторый код перед методами onClick. Я попробовал следующее:

// 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();

Это не работает, потому что при вызове нового метода oldOnClick будет указывать на метод с последней итерации, а не на метод to, когда он был назначен.

Есть ли простое решение, которое я пропускаю?

Ответы [ 4 ]

3 голосов
/ 21 июня 2009

Что вам нужно, это закрытие:

for(var i=0, l=arr.length; i<l; i++){
 (function(i){
   var oldOnclick = arr[i].onClick; 
   //etc.
 })(i);
}
1 голос
/ 21 июня 2009

вы пробовали с какой-то фреймворк AOP для Javascript?

например, используя плагин jQuery AOP:

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

проверьте также здесь .

1 голос
/ 21 июня 2009

Правила привязки Javascript довольно странные. Действительно, JavaScript довольно странный.

Я не знаю, что бы я назвал этот способ исправить это, но, введя подфункцию, вы можете ввести еще одну привязку и тем самым решить эту конкретную проблему.

Ваш код (модифицированный для быстрого взлома Chrome) становится:

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();
    }  
}

Приведенный выше код выдает три предупреждения: a, b, c. Все, что заменит «// Новый код», будет выполнено в нужное время.

0 голосов
/ 21 июня 2009
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"
...