Logging events and data with console.log and other related functions makes JavaScript debugging easier, but too much information can also be problematic. The obvious and easiest solution is to make a proxy function that can conditionally log messages.

var DEBUG = true;

function _log() {
if (DEBUG) {
console.log(arguments);
}
}

_log('message', data);


This solution has one problem, though. Whenever console.log is called, the browser console records the file and line number where the log entry originated. With the above approach, all entries will show that they originated from within the _log function.

I recently had to address this issue in one of my projects, and here is how I solved it. For the impatient,

var DEBUG = true;
var _log = DEBUG ? console.log.bind(console) : function () {};


My original idea was to conditionally assign the _log function dynamically to console.log if logging was enabled, and a void function otherwise. It was then that I learned that WebKit’s implementation of console.log expects this to point to the console object, so the following line, though elegant, did not work in Chrome or Safari:

var _log = DEBUG ? console.log : function () {};


Thus I employed the ECMAScript 5 Function.prototype.bind method to set this to console within the console.log function. If compatibility for older browsers is required, the following code from the MDN website provides the Function.prototype.bind functionality:

if (!Function.prototype.bind) {
Function.prototype.bind = function (that) {
if (typeof this !== 'function')
throw new TypeError('Function.prototype.bind - "this" is not callable');

var args = Array.prototype.slice.call(arguments, 1),
func = this,
nop = function () {},
bound = function () {
return func.apply(this instanceof nop && that ? this : that,
args.concat(Array.prototype.slice.call(arguments)));
};
nop.prototype = this.prototype;
bound.prototype = new nop();
return bound;
};
}