2013-07-18 3 views
1

Есть ли способ добавить до и после функции вызова в Javascript? У меня есть что-то вроде этого:Ruby style before() и after() фильтры для Javascript

var A = { 

    a1: function() { 

    }, 
}; 

var B = { 

    b1: function() { 

    } 
}; 

A.a1(); 
B.b1(); 
//so on .. 

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

Update: В рубина

before_filter :some_function 
after_filter :some_other_function 

будет выполнять some_function перед каждым вызовом функции в этом классе и some_other_function после каждого вызова функции. Также это не встречается в Application Controller в Rails.

+1

Выполните функцию, называемую 'before' и' after' в каждом объекте, вызовите 'before' в первой строке вашей функции и' after' в конце? – tymeJV

+0

Возможно, вам поможет дополнительная помощь, если вы объясните, что делают функции 'before' и' after' в Ruby. – Shawn31313

ответ

1

Попробуйте изменить все функции в объекте:

var beforeAll = function(o, f) { 
    for (var p in o) { 
    if (o.hasOwnProperty(p) && typeof(o[p]) === "function") { 
     o[p] = (function(oldF) { 
     return function() { 
      f.apply(this, arguments); 
      return oldF.apply(this, arguments); 
     }; 
     }(o[p])); 
    } 
    } 
}; 

var A = { 
    func1: function() {console.log('func1')}, 
    func2: function() {console.log('func2')} 
}; 

beforeAll(A, function() {console.log('before')}); 

A.func1(); 
A.func2(); 

(Вы можете создать подобный один для afterAll).

Fiddle here.

Отметьте, что вам необходимо указать старая функция в цикле, чтобы связать ее правильно. Больше информации here.

0

если вы сохраните Orginal функцию и вызвать ее после (или до), как:

var A = { 

    a1: function() { 

    } 
}; 

var orginal = A.a1 
A.a1 = function(){ 
    // the before code 
    orginal.apply(this, arguments) 
} 

для всех реквизита

for(prop in A){ 
    var orginal = prop 
    A[prop] = function(){ 
    //before code 
    orginal.apply(this, arguments) 
    } 
} 

я оставить проверку типа как изгонять для читателя:)

+0

Можно ли сделать это для всех функций в объекте? Итак, что-то вроде 'for (keys in A) {if (typeof key == function) {// сохранить оригинал и определить новый}}' – Deepak

+0

yes i updated my anwser – VeXii

+0

Вы должны проверить, является ли свойство функцией и использование применяется как в первом фрагменте. И будьте в курсе «этого» значения :) – Ivancho

2

Вы можете написать функцию, которая перечисляет поля объекта и обертывает его функции в новых:

function addBefore(obj, func) { 
    for (var prop in obj) { 
     if (obj.hasOwnProperty(prop) && typeof obj[prop] === 'function') { 
      (function() { 
       var oldFunc = obj[prop]; 
       obj[prop] = function() { 
        func.apply(obj, arguments); 
        return oldFunc.apply(obj, arguments);    
       } 
      }()); 
     } 
    } 
} 
var A = { 

    a1: function (a, b) { 
    alert('A.a1'); 
    return a + b; 
    }, 
    a2: function (a, b) { 
    alert('A.a2'); 
    return a + b; 
    } 
}; 
addBefore(A, function (a, b) { 
    alert('before ' + a + ', ' + b); 
}); 
A.a1(1, 2); 
A.a2(3, 4); 

Аналогичным образом вы можете написать функцию addAfter, просто переключите два вызова на функцию apply().

+1

+1 Я сделал [точно так же, как вы] (http://jsfiddle.net/LTCpj/1/) .... –

+0

Я знаю, что принял этот ответ, но я столкнулись с этим осложнением. когда A имеет два метода или более методов, то старая ссылка функции всегда возвращает последнюю функцию в объекте вместо соответствующей функции. См. Обновление, которое я сделал на скрипке @ Jordão по адресу http://jsfiddle.net/LTCpj/3/. Есть ли способ избежать этого? – Deepak

+1

@ Deepak: Хорошая добыча! Исправлено [здесь] (http://stackoverflow.com/a/17756830/31158). –

0

В javascript соглашение заключается в использовании обратных вызовов для такого рода вещей. Так что если вы хотите, чтобы стрелять одну функцию только после того, как другой, это будет выглядеть примерно так:

var a1 = function(callback){ 
    console.log('doing function things la la'); 
    callback(); 
} 

Теперь, когда вы вызываете функцию a1, вы могли бы сделать что-то вроде этого:

a1(function(){ 
    console.log('this is only printed at the end!'); 
}); 

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

Если вы говорите о том, чтобы запустить определенную функцию перед большим количеством методов, которые не имеют обратного вызова, я думаю, что лучший способ - просто обернуть их функцией, которая принимает ваши основные функции как обратный вызов, что-то вроде этого:

var a1 = function(){ console.log('a1'); } 
var a2 = function(){ console.log('a2'); } 
var a3 = function(){ console.log('a3'); } 
var a4 = function(){ console.log('a4'); } 

var before_filter = function(callback){ 
    console.log('doing some stuff before whoo!'); 
    callback(); 
} 

[a1, a2, a3, a4].map(function(fn){ 
    before_filter(fn); 
}); 

Позвольте мне знать, если это не то, что вы были после, и я был бы счастлив, чтобы добавить больше вариантов - Есть много потенциальных способов справиться с этой проблемой, это зависит только от на что именно вы ищите. Было бы сложно сделать это чистым, как рубин, так как before_filter s не встроены в javascript изначально, но, глядя на последний пример, вы можете видеть, что было бы легко получить его довольно близко.Еще одна альтернатива аналогична последней:

var a1 = function(){ console.log('a1'); } 
var a2 = function(){ console.log('a2'); } 
var a3 = function(){ console.log('a3'); } 
var a4 = function(){ console.log('a4'); } 
var before = function(){ console.log('doing before stuff'); } 

var before_filter = function(before_fn, fn){ 
    before_fn(); 
    fn(); 
} 

[a1, a2, a3, a4].map(function(fn){ 
    before_filter(before, fn); 
}); 
Смежные вопросы