Skip to content

Instantly share code, notes, and snippets.

@megawac
Forked from bgrins/Log-.md
Last active August 29, 2015 13:56
Show Gist options
  • Save megawac/8890711 to your computer and use it in GitHub Desktop.
Save megawac/8890711 to your computer and use it in GitHub Desktop.

Javascript log Function

Every time I start a new project, I want to pull in a log function that allows the same functionality as the console.log, including the full functionality of the Console API.

There are a lot of ways to do this, but many are lacking. A common problem with wrapper functions is that the line number that shows up next to the log is the line number of the log function itself, not where log was invoked. There are also times where the arguments get logged in a way that isn't quite the same as the native function.

This is an attempt to once and for all document the function that I pull in to new projects. There are two different options:

  • The full version: Inspired by the plugin in HTML5 Boilerplate. Use this if you are writing an application and want to create a window.log function. Additionally, this will set all the console methods to an empty function if they don't exist to prevent errors from accidental console.log calls left in your code. Put this snippet at the top of the rest of your scripts - it will need to be evaluated first thing to work.
  • The portable version: Use this if you want to use it inside a plugin and/or don't want to muck with the global namespace. Just drop it at the bottom of your plugin and log away. log can be called before the function declaration, and will not add anything to the window namespace or modify the console objects.

View a live demo here: http://jsfiddle.net/bgrins/MZWtG/

// Full version of `log` that:
// * Prevents errors on console methods when no console present.
// * Exposes a global 'log' function that preserves line numbering and formatting.
(function(console, noop) {
[
'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
'timeStamp', 'trace', 'warn'
].forEach(function(method) {
// Only stub undefined methods.
if (!console[method]) console[method] = noop;
});
if (console.log.bind) {
window.log = console.log.bind(console);
} else {
window.log = function() {
Function.prototype.apply.call(console.log, console, arguments);
};
}
})(window.console = window.console || {}, function(){});
// Portable version of `log` that:
// * Doesn't expose log to the window.
// * Allows log() to be called above the function declaration.
// Because of this, you can just throw it in the bottom of a plugin and it won't mess with global scope or clutter your code
(function() {
// Your code here... log() away
function log () {
/* jshint -W021 */
if (window.console) {
// Only run on the first time through - reset this function to the appropriate console.log helper
if (Function.prototype.bind) {
log = Function.prototype.bind.call(console.log, console);
}
else {
log = function() {
Function.prototype.apply.call(console.log, console, arguments);
};
}
log.apply(this, arguments);
}
}
})();
// All at once (minified version):
function log(){/* jshint -W021 */if(window.console){if(Function.prototype.bind)log=Function.prototype.bind.call(console.log,console);else log=function(){Function.prototype.apply.call(console.log,console,arguments);};log.apply(this,arguments);}}
/* Log statements with `log` and `console.log` should appear the same, and show the correct line numbers */
function Test() {}
Test.prototype.extraMethod = function() { }
Test.methodAttachedToFunction = function(withParam) { }
function logAllWithWrapper() {
log("A single string");
log(123);
log(["An", "Array", "Of", "Strings"]);
log("The %s jumped over %d tall buildings", "person", 100);
log("The", "person", "jumped over ", 100, " tall buildings");
log("The object %o is inspectable!", { person: { jumpedOver: [100, "tall buildings"]}});
log('%cThis is red text on a green background', 'color:red; background-color:green');
log({ an: "obj", withNested: { objects: { inside: "of", it: true }}});
log(Test, Test.methodAttachedToFunction);
log(new Test());
log(document);
log(document.body);
log(document.body.childNode);
}
function logAllWithNative() {
console.log("A single string");
console.log(123);
console.log(["An", "Array", "Of", "Strings"]);
console.log("The %s jumped over %d tall buildings", "person", 100);
console.log("The", "person", "jumped over ", 100, " tall buildings");
console.log("The object %o is inspectable!", { person: { jumpedOver: [100, "tall buildings"]}});
console.log('%cThis is red text on a green background', 'color:red; background-color:green');
console.log({ an: "obj", withNested: { objects: { inside: "of", it: true }}});
console.log(Test, Test.methodAttachedToFunction);
console.log(new Test());
console.log(document);
console.log(document.body);
console.log(document.body.childNode);
}
log("\n-----------");
log("Logging all expressions with wrapper log function");
log("-----------\n");
logAllWithWrapper();
log("\n-----------");
log("Logging all expressions with native console.log function");
log("-----------\n");
logAllWithNative();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment