Decorator Functions and Console.log

Today I wanted to go over Decorator functions, what they are, and what they do. But I’ve noticed that there are a lot of blog posts on the subject. Because of this, instead of simply going over Decorator functions, I decided to make this blog post more interesting. I’m going to show you how you can use Decorator functions to modify your console.log statements. In order to get started, first let’s do a quick refresher of what decorator functions are:

A function decorator accepts a function, wraps (or decorates) it’s call and returns the wrapper, which alters default behavior. Let’s look at an example:

function checkPermissionDecorator(f) {
  return function() {
    if (user.isAdmin()) f()
    else alert('Not an admin yet')
  }
}
// Usage: make save check permissions
save = checkPermissionDecorator(save)
// Now save() calls will check permissions

Decorator functions can also be used to “decorate” objects with new properties or methods, without having to use inheritance. Because of this, decorators are a very good choice when you are working on legacy projects and you need to add a method or property to a particular class, but you can’t change that class’s constructor in case if might affect other dependencies. If you would like to read more about how decorators work, I recommend reading either one of these posts http://robdodson.me/javascript-design-patterns-decorator/, http://javascript.info/tutorial/decorators.

Now that you know what decorators are, let’s get to the fun stuff. As we’ve seen so far a decorator function can take a function and modify its methods, so let’s take a look at what we can do with console.log.

(function () {
  var log = console.log;
  console.log = function () {
    log.call(this, 'ERROR!!!');
    log.apply(this, Array.prototype.slice.call(arguments));
  };
}());

If you inserted this into your friend’s website it would produce “Error” before every message logged out to the console. But we can do more than just log out a message with this.

(function () {
  var log = console.log;
  console.log = function () {
    alert(Array.prototype.slice.call(arguments))
    log.apply(this, Array.prototype.slice.call(arguments));
  };
}());

Now we’re not only logging out those results to the console, but we are also alerting them on the screen. That doesn’t mean we have to be logging out anything at all, we could replace the console.log entirely:

(function () {
  var log = console.log;
  console.log = function () {
  alert("hello")
  };
}());

Let me give you one more example to show you that there really aren’t any limits to what you could do:

(function () {
  var log = console.log;
  console.log = function () {
  document.body.style.background = 'black';   
  log.apply(this, Array.prototype.slice.call(arguments));
  };
}());

Now when you try to use console.log your background will become black. And as long as you continue to call log.apply(this, Array.prototype.slice.call(arguments));” the application will continue to log to the console as if nothing has changed. This is all due to the power of decorator functions. I hope that this quick demo has made you a bit more excited about learning how to use decorator functions, since they are an incredibly useful tool that every JavaScript programmer should be familiar with.

Paulo Diniz