I'm trying to implement conditional assignment of the console.log() method to a variable as follows:
var dbglevel = 1;
var dbg = (dbglevel > 0) ? console.log : function(){};
dbg('message'); // throws TypeError
TypeError: 'log' called on an object that does not implement interface Console.
It used to work but something changed in Firefox 30. Now I have no idea if it was ever supposed to work. The reason I have my doubts is that I've seen the same thing with the document object. Compare the results of these two function assignments, the first is a function wrapper and the second is direct assignment to the method:
function qs1(q) { return document.querySelector(q); }; // wrapper
qs1('head'); // works
var qs2 = document.querySelector;
qs2('head'); // throws TypeError
TypeError: 'querySelector' called on an object that does not implement interface Document.
What am I seeing here? Why does direct assignment of the method to a variable break its "interface" to it's parent object?
My reason for wanting to do this is twofold:
1.) The assignment syntax is shorter and I don't need to worry about declaring arguments,
2.) More importantly, I want my dbg() calls to report the correct file and line number to the console. If the function is a wrapper the console always shows the line number of the console.log call in that wrapper. I don't want to emulate the line number logging because the normal method of calling console.log
directly gives you a clickable link to view source centered on the line that called it.
I'm not looking for a workaround involving plugins like FireBug, pre-processing (LESS/SASS), or third-party scripts. The solution only needs to work on vanilla Firefox 30 or later and the specific problem I'm trying to solve is how to compress the following code on every line I want to conditionally log:
if (typeof cfg.DEBUG != 'undefined' && cfg.DEBUG > 2) console.log(something);
... to this ...
dbg(something);
... where the dbg()
function does any appropriate conditional evaluation and then shows the same line number as if I had called console.log directly.
In JavaScript, we can simply reassign the new value to the variable. When we change the value of a variable, we do not use var again. We simply use the = to give the variable a new value.
Functions stored in variables do not need function names. They are always invoked (called) using the variable name. The function above ends with a semicolon because it is a part of an executable statement.
In the following example, initially, the object type is created and later on, the properties of the object were created. Once the creation of properties is done, a method is assigned to each of the objects and the properties were accessed using the method as our requirement.
There is a simple workaround:
var dbglevel = 1;
var dbg = (dbglevel > 0) ? function(msg){console.log(msg);} : function(){};
dbg('message'); // prints message
By the way, assigning a native function to a var
throws TypeError
in Chrome as well.
The problem is binding: when you are aliasing functions like you did, they are called on the global object, and instead you need to have them bound to console
or document
in turn.
So the right way to your aliasing is like:
var dbg = console.log.bind(console);
or
var qs2 = document.querySelector.bind(document);
Assuming you are running ES5 at least. So, if you need back compatibility, you'd probably want to use something like the workaround above (perhaps something more elaborate to take into account a variable number of arguments, using apply
and the arguments
object).
If you are sure you have access to ES5 features, use:
var dbglevel = 1;
var dbg = (dbglevel > 0) ? console.log.bind(console) : function(){};
dbg('message'); // prints message
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With