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);
}
}
// in your code:
_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;
};
}