JavaScript decorator pattern
I don’t care how many other places this is on the net, file this one under “so I won’t need to look ever again.”
I needed to augment an existing JavaScript function by applying a decorator to it, where I needed to dynamically add special behavior for this one page. Ideally, I could have bound to some event, but a decorator worked just as well. Instead of doing some custom JavaScript for decorating this one method, I modified the Function prototype, to add two new methods, “before” and “after”:
Function.prototype.method = function(name, func) { this.prototype[name] = func; return this; }; Function.method('before', function(beforeFunc) { var that = this; return function() { beforeFunc.apply(null, arguments); return that.apply(null, arguments); }; }); Function.method('after', function(afterFunc) { var that = this; return function() { var result = that.apply(null, arguments); afterFunc.apply(null, arguments); return result; }; });
Each decorator method captures the original method (in the “that” variable) and returns a new method that calls the original and new method passed in, all without modifying the original method. With these new Function prototype methods, I can do some highly interesting code:
var test = function(name) { alert(name + ' is a punk.'); }; test('Nelson Muntz'); test = test.before(function(name) { alert(name + ' is a great guy.'); }); test('Milhouse'); test = test.after(function(name) { alert(name + ' has a fat head.'); }); test('Jimmy');
We see from this code, in succession, alerts:
- “’Nelson Muntz is a punk”
- “Milhouse is a great guy”
- “Milhouse is a punk”
- “Jimmy is a great guy”
- “Jimmy is a punk”
- “Jimmy has a fat head”
This code was brought to you by lessons learned from the awesome JavaScript book, “JavaScript: The Good Parts”, and the magic of closures.