Есть ли способ выполнить функцию в объекте JS до выполнения другой вызванной функции?

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

Пример объекта JS

var OmnitureCall = {
    reportA: function() {
        /* random actions */
    },
    reportB: function() {
        /* random actions */
    }
    ...
};

Другой файл JS, вызывающий объект

OmnitureCall.reportA(...);

Где-то во внешнем файле JS происходит несколько reportA, хотя должен произойти только один, поэтому я хотел бы отладить основной объект и посмотреть, когда вызываются различные функции отчета, и посмотреть, где запускается двойное событие. Тем не менее, единственный способ, которым я пока вижу это, — иметь основную функцию внутри объекта OmnitureCall, которая действует как «обработчик» для всех вызовов, выполняет некоторую базовую отладку, а затем запускает вызванную функцию.

Пример обработчика объектов JS

var OmnitureCall = {
    handler: function(callback) {
        console.log('something is called');
        if(typeof(callback) === "function") {
            callback();
        }
    },
    reportA: function() {
        this.handler(function(){
            /* random actions */
        });
    },
    reportB: function() {
        this.handler(function(){
            /* random actions */
        });
    }
    ...
};

Недостатки:

  1. Есть более 100 функций, которые мне пришлось бы скопировать и вставить и this.handler и исправить
  2. В большинстве этих функций ключевое слово «this» используется для ссылки на другие функции внутри этого объекта OmnitureCall, и я беспокоюсь, что контекст этого «this», на который ссылается, будет потерян, если все это будет обернуто как функция обратного вызова, а затем вызвано.

Итак, мой вопрос к любым разработчикам JS: есть ли способ прикрепить функцию к этому объекту, которая всегда будет вызываться до того, как какая-либо функция была фактически вызвана (имейте в виду, что я также пытаюсь документировать это имя указанной функции, которая называется, чтобы я мог выяснить, что увольняется дважды).

Если это невозможно, и идея функции обработчика - единственное, что может работать, кто-нибудь знает, как сохранить контекст "это", относящийся к объекту в целом, если функция передается в качестве параметра обработчику, а затем вызывается ?

Большое спасибо..


person user2744382    schedule 05.12.2013    source источник


Ответы (2)


Прокси — это то, что вам нужно, но они широко не реализованы, поэтому я бы пока не рекомендовал их. Но на будущее, вот как это будет выглядеть:

// Your original object
var OmnitureCall = {
    reportA: function() {
        console.log(arguments, 'hello from report A');
    },
    reportB: function() {
        console.log(arguments, 'hello from report B');
    }
    // ...
};

// Create our proxy
var OmnitureCall = new Proxy(OmnitureCall, 
{
    // Since we want to see the calls to methods, we'll use get
    get: function(proxy, property)
    {
        // Tell us what we're calling
        console.log('calling ' + property);

        // Return it if it exists
        return proxy[property] || proxy.getItem(property) || undefined;
    }
});

// Returns "calling reportA", ["test", "foo"], "hello from report A":
OmnitureCall.reportA('test', 'foo');           

// Returns "calling reportB", [["array", "of", "args"]], "hello from report B":         
OmnitureCall.reportB(['args', 'is', 'an', 'array']); 

Хотя код Бретта должен работать, вам нужно будет изменить все вызовы объекта. Например. ты больше не можешь OmnitureCall.reportA();. Должно быть OmnitureCall.handler('reportA'). Вы можете или не можете контролировать это, или может оказаться слишком сложно изменить все ссылки.

Используя исходную настройку обработчика, вы действительно можете передать ссылку this, используя apply или call:

var OmnitureCall = {
    handler: function(callback, args) {
        if(typeof(callback) === "function") {
            callback.apply(this, args);
        }
    },
    reportA: function() {
        this.handler(function(){
            console.log(this);
        });
    },
    reportB: function() {
        this.handler(function(){
            console.log(arguments);
        }, arguments);
    }
    // ...
};

// Outputs Object {handler: function, reportA: function, reportB: function}
OmnitureCall.reportA();

// Outputs "test", ["foo", 1]
OmnitureCall.reportB('test', ['foo', 1]);
person MisterPhilip    schedule 10.12.2013

Вы можете сделать что-то вроде этого http://jsfiddle.net/L4Z8U/ и просто вызывать функции с обработчиком .

window.OmnitureCall = {
     handler: function(callback) {
        console.log('something is called',typeof(this[callback]));
        if(typeof(this[callback]) === "function") {
            this[callback]();
        }
    },
    reportA: function() {
         console.log('reportA fired');
     },
    reportB: function() {
        console.log('reportB fired');
    }

};

Изменить: я сделал это, прежде чем использовать «это» в этом контексте без проблем.

person BrettAHale    schedule 05.12.2013