Add a line of code to ALL functions

2020-01-27 08:46发布

问题:

So I am working in JS a lot, and I am working a lot with events (try to stay as modular as possible). Current I am calling Event.fire('eventName') at the end of every function. I am looking for a way to have ANY function in my object/class automatically call an Event.fire([function name]) at the end of all functions

Example:

function MyClass(){
   this.on('someFunc', this.funcTwo);
   this.someFunc();
}
MyClass.prototype.on = function( event ){
   // the event stuff //
}
MyClass.prototype.someFunc = function(){
   console.log('someFunc');
}
MyClass.prototype.funcTwo = function(){
   console.log('funcTwo');
}

回答1:

You could try something like this, dynamically modifying your functions:

var obj = MyClass.prototype;
for (var prop in obj)
    if (typeof obj[prop] == "function") // maybe also prop != "on" and similar
        (function(name, old) {
            obj[prop] = function() {
                var res = old.apply(this, arguments);
                Event.fire(name);
                return res;
            };
        })(prop, obj[prop]);


回答2:

You could create a function that builds functions which always have that functionality:

var eventFunctionFactory = function(fn, e) {
  if (typeof fn != 'function' || typeof e != 'function') {
    throw new TypeError('Invalid function!');
  }

  return function(/* arguments */) {
    // Convert arguments to array
    var args = Array.prototype.slice.call(arguments);

    // Fire event
    Event.fire(e);

    // Call the function with the applied arguments
    // Return its result
    return fn.apply(fn, args);
  };
};

var myClass = function() {
  this.someFunction = eventFunctionFactory(
                        // Function
                        function(a, b) {
                          return a + b;
                        },

                        // Event
                        function() {
                          console.log('someFunction fired!');
                        }
                      );
};

var myObj = new myClass();

// Outputs:
// someFunction fired!
// 3
console.log(myObj.someFunction(1, 2));


回答3:

the easiest way is to have a proxy class. assuming your regular class is class A and the proxy class is class B. Class B has an instance of class A internally. class B also has a stub for each Class A function that calls its internal class a instance. Then, you can add any code you want to the original class by simply adding code to the associated stub - before or after the function call to class A.

To be able to use the enhanced class, all you need to do is modify the rest of your app to instantiate class B instead of class A. The advantage with this method is your original class remains intact.