有没有办法在执行另一个被调用的函数之前在JS对象中执行函数?

时间:2013-12-05 19:02:38

标签: javascript class oop adobe-analytics

我正在尝试在JS对象中调试大量的JS代码。这个JS对象中大约有150个函数可以通过单独的脚本单独调用。

JS对象示例

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

其他JS文件调用对象

OmnitureCall.reportA(...);

在外部JS文件的某个地方,当只有一个应该发生时,会发生多个reportA,这就是为什么我想调试主对象并查看何时调用各种报告函数并查看double事件被触发的位置。但是,到目前为止,我能看到这样做的唯一方法是在OmnitureCall对象中有一个main函数,它充当所有调用的“处理程序”,并进行一些基本调试,然后运行被调用的函数。

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'的上下文将会丢失然后叫。
  3. 所以我对任何JS开发者的问题,是否有一种方法可以将函数附加到此对象,在实际调用任何函数之前将始终调用该函数(请记住,我也试图记录所述函数的名称)被调用,所以我可以弄清楚被解雇的是什么两次)。

    如果那是不可能的并且处理函数的想法是唯一可行的,那么有没有人知道如果函数作为参数传递给处理函数,如何保留'this'的上下文引用整个对象然后叫?

    非常感谢..

2 个答案:

答案 0 :(得分:1)

Proxies是您正在寻找的,但它们没有得到广泛实施 - 因此我还不推荐它。但是为了将来,这就是它的样子:

// 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']); 

虽然Brett的代码应该可行,但您需要更改对该对象的所有调用。例如。你不能再做OmnitureCall.reportA();了。它需要OmnitureCall.handler('reportA')。您可能已经或可能无法控制此情况,或者可能难以更改所有引用。

使用原始处理程序设置,您确实可以使用thisapply传递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]);

答案 1 :(得分:0)

您可以执行类似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');
    }

};

编辑:我已经在这个上下文中使用“this”之前没有问题