DevTools Console - Turn it off - javascript

I'm currently building a library in Javascript and really like Google's DevTools for debugging it. Unfortunately I don't want my library to log when I release.
This is how my logger is currently setup.
var debug = false;
var increaseSomething = function()
{
// Random Code...
if (debug) { console.log("Increased!"); }
}
Unfortunately this is quite annoying, I shouldn't have to check if debug is on before logging to the console every call.
I could try to encapsulate the console in my own logging object but I feel that wouldn't be such a great idea. Any thoughts?

You could do this?
if (!debug) {
console.log = function() {/* No-op */}
}
As you mentioned, you might not want to kill all logging for everyone. This is how I usually go about it. Define these in some utility file, as global functions. I usually add additional functions for LOG, WARN, ERROR and TRACE, and log these based on a verbosity level.
// Define some verbosity levels, and the current setting.
_verbosityLevels = ["TRACE", "LOG", "WARN", "ERROR"];
_verbosityCurrent = _verbosityLevels.indexOf("LOG");
// Helper function.
var checkVerbosity = function(level) {
return _verbosityLevels.indexOf(level) <= _verbosityCurrent;
}
// Internal log function.
var _log = function(msg, level) {
if(!debug && checkVerbosity(level)) console.log(msg);
}
// Default no-op logging functions.
LOG = function() {/* no-op */}
WARN = function() {/* no-op */}
// Override if console exists.
if (console && console.log) {
LOG = function(msg) {
_log(msg, "LOG");
}
WARN = function(msg) {
_log(msg, "WARN");
}
}
This also allows you to add important information to your log, such as time, and caller locations.
console.log(time + ", " + arguments.callee.caller.name + "(), " + msg);
This may output something like this:
"10:24:10.123, Foo(), An error occurred in the function Foo()"

I thought about encapsulating the console logger again and instead of coming up with an entire object to encapsulate the console I created a function that takes in a console method. Then it checks if debugging is on and calls the function.
var debug = true;
var log = function (logFunction) {
if (debug) {
logFunction.apply(console, Array.prototype.slice.call(arguments, 1));
}
};
var check = function (canvas) {
log(console.groupCollapsed, "Initializing WebGL for Canvas: %O", canvas);
log(console.log, "cool");
log(console.groupEnd);
};
check(document.getElementById('thing'));
I do like #Aesthete's ideas but I'm not yet wanting to make the encapsulated console.
Here is the jsfiddle as example: http://jsfiddle.net/WRe29/
Here I add a debugCall to the Objects prototype. Same as the log function just a different name so theirs no 'overlap' Now any object can call debugCall and check its debug flag.
Object.prototype.debugCall = function(logFunction)
{
if (this.debug) { logFunction.apply(console, Array.prototype.slice.call(arguments, 1)); }
};
var Thing = { debug : true /*, other properties*/ };
Thing.debugCall(console.log, "hello world");
EDIT:
My initial thoughts were to use an object as the 'configuration' to indicate whether the object should be logging. I've used this a while and liked the configuration concept but didn't think everyone would be so keen to use configuration objects in their code alongside a function being passed to a extended function on object. Thus I took the concept and instead looked at function decoration.
Function.prototype.if = function (exp) {
var exFn = this;
return function () {
if (exp) exFn.apply(this, arguments);
};
};
var debug = false;
console.log = console.log.if(debug);
console.group = console.group.if(debug);
// Console functions...
myFunction = myFunction.if(debug);
It's very simple almost unnecessary to even have a decoration function that checks an expression but I am not willing to put if statements everywhere in my code. Hope this helps someone out maybe even spark their interest with function decoration.
Note: This way will also kill logging for everyone unless you setup the if extension correctly ;) *cough some type of object/library configuration indicating debug

https://github.com/pimterry/loglevel
Log level Library::Try whether this suits ur need.

Related

Pass an object that has an optional property to a function that guarantee it will not be undefined but editor/compiler still think it can be undefined

function f1(
toolbox: {
tool1?: Tool1,
tool2?: Tool2,
}
) {
if (!toolbox.tool1) {
toolbox.tool1 = fetchTool1();
}
if (!toolbox.tool2) {
toolbox.tool2 = fetchTool2();
}
// Do something else
}
function f2(
toolbox: {
tool1?: Tool1,
tool2?: Tool2,
}
) {
f1(toolbox);
// tool1 and tool2 are no longer undefined.
const x = toolbox.tool1.value // Editor shows error, tool1 may be undefined.
}
The design above passes a toolbox object to different functions, so the program doesn't need to fetch the tools that are already fetched by other functions. The problem is, even if I know for sure toolbox.tool1 and toolbox.tool2 will not be undefined after calling f1, the editor still shows error.
I know I can use exclamation mark like const x = toolbox.tool1!.value, or maybe just turn off the warning. But I'm looking for a way that is more friendly to the default type checking.
I have tried let f1 return the toolbox that has no question mark in it, and call toolbox = f1(toolbox). It doesn't work, the line const x = toolbox.tool1.value still shows error.
You're looking for asserts.
f1 now looks like this:
function f1(
toolbox: {
tool1?: Tool1,
tool2?: Tool2,
}
): asserts toolbox is { tool1: Tool1; tool2: Tool2 } {
You can think of this as "changing" the type in the scope it was called:
f1(toolbox);
toolbox // now { tool1: Tool1; tool2: Tool2 }
const x = toolbox.tool1.value; // fine
Playground

How to let callee know who is the caller [duplicate]

function main()
{
Hello();
}
function Hello()
{
// How do you find out the caller function is 'main'?
}
Is there a way to find out the call stack?
Note that this solution is deprecated and should no longer be used according to MDN documentation
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller
function Hello()
{
alert("caller is " + Hello.caller);
}
Note that this feature is non-standard, from Function.caller:
Non-standard
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.
The following is the old answer from 2008, which is no longer supported in modern Javascript:
function Hello()
{
alert("caller is " + arguments.callee.caller.toString());
}
StackTrace
You can find the entire stack trace using browser specific code. The good thing is someone already made it; here is the project code on GitHub.
But not all the news is good:
It is really slow to get the stack trace so be careful (read this for more).
You will need to define function names for the stack trace to be legible. Because if you have code like this:
var Klass = function kls() {
this.Hello = function() { alert(printStackTrace().join('\n\n')); };
}
new Klass().Hello();
Google Chrome will alert ... kls.Hello ( ... but most browsers will expect a function name just after the keyword function and will treat it as an anonymous function. An not even Chrome will be able to use the Klass name if you don't give the name kls to the function.
And by the way, you can pass to the function printStackTrace the option {guess: true} but I didn't find any real improvement by doing that.
Not all browsers give you the same information. That is, parameters, code column, etc.
Caller Function Name
By the way, if you only want the name of the caller function (in most browsers, but not IE) you can use:
arguments.callee.caller.name
But note that this name will be the one after the function keyword. I found no way (even on Google Chrome) to get more than that without getting the code of the whole function.
Caller Function Code
And summarizing the rest of the best answers (by Pablo Cabrera, nourdine, and Greg Hewgill). The only cross-browser and really safe thing you can use is:
arguments.callee.caller.toString();
Which will show the code of the caller function. Sadly, that is not enough for me, and that is why I give you tips for the StackTrace and the caller function Name (although they are not cross-browser).
I usually use (new Error()).stack in Chrome.
The nice thing is that this also gives you the line numbers where the caller called the function. The downside is that it limits the length of the stack to 10, which is why I came to this page in the first place.
(I'm using this to collect callstacks in a low-level constructor during execution, to view and debug later, so setting a breakpoint isn't of use since it will be hit thousands of times)
I know you mentioned "in Javascript", but if the purpose is debugging, I think it's easier to just use your browser's developer tools. This is how it looks in Chrome:
Just drop the debugger where you want to investigate the stack.
In both ES6 and Strict mode, use the following to get the Caller function
console.log((new Error()).stack.split("\n")[2].trim().split(" ")[1])
Please note that, the above line will throw an exception if there is no caller or no previous stack. Use accordingly.
To get callee (the current function name), use:
console.log((new Error()).stack.split("\n")[1].trim().split(" ")[1])
If you are not going to run it in IE < 11 then console.trace() would suit.
function main() {
Hello();
}
function Hello() {
console.trace()
}
main()
// Hello # VM261:9
// main # VM261:4
You can get the full stacktrace:
arguments.callee.caller
arguments.callee.caller.caller
arguments.callee.caller.caller.caller
Until caller is null.
Note: it cause an infinite loop on recursive functions.
To recap (and make it clearer) ...
this code:
function Hello() {
alert("caller is " + arguments.callee.caller.toString());
}
is equivalent to this:
function Hello() {
alert("caller is " + Hello.caller.toString());
}
Clearly the first bit is more portable, since you can change the name of the function, say from "Hello" to "Ciao", and still get the whole thing to work.
In the latter, in case you decide to refactor the name of the invoked function (Hello), you would have to change all its occurrences :(
I would do this:
function Hello() {
console.trace();
}
You can use Function.Caller to get the calling function. The old method using argument.caller is considered obsolete.
The following code illustrates its use:
function Hello() { return Hello.caller;}
Hello2 = function NamedFunc() { return NamedFunc.caller; };
function main()
{
Hello(); //both return main()
Hello2();
}
Notes about obsolete argument.caller: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/caller
Be aware Function.caller is non-standard: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller
Looks like this is quite a solved question but I recently found out that callee is not allowed in 'strict mode' so for my own use I wrote a class that will get the path from where it is called. It's part of a small helper lib and if you want to use the code standalone change the offset used to return the stack trace of the caller (use 1 instead of 2)
function ScriptPath() {
var scriptPath = '';
try {
//Throw an error to generate a stack trace
throw new Error();
}
catch(e) {
//Split the stack trace into each line
var stackLines = e.stack.split('\n');
var callerIndex = 0;
//Now walk though each line until we find a path reference
for(var i in stackLines){
if(!stackLines[i].match(/http[s]?:\/\//)) continue;
//We skipped all the lines with out an http so we now have a script reference
//This one is the class constructor, the next is the getScriptPath() call
//The one after that is the user code requesting the path info (so offset by 2)
callerIndex = Number(i) + 2;
break;
}
//Now parse the string for each section we want to return
pathParts = stackLines[callerIndex].match(/((http[s]?:\/\/.+\/)([^\/]+\.js)):/);
}
this.fullPath = function() {
return pathParts[1];
};
this.path = function() {
return pathParts[2];
};
this.file = function() {
return pathParts[3];
};
this.fileNoExt = function() {
var parts = this.file().split('.');
parts.length = parts.length != 1 ? parts.length - 1 : 1;
return parts.join('.');
};
}
heystewart's answer and JiarongWu's answer both mentioned that the Error object has access to the stack.
Here's an example:
function main() {
Hello();
}
function Hello() {
try {
throw new Error();
} catch (err) {
let stack = err.stack;
// N.B. stack === "Error\n at Hello ...\n at main ... \n...."
let m = stack.match(/.*?Hello.*?\n(.*?)\n/);
if (m) {
let caller_name = m[1];
console.log("Caller is:", caller_name);
}
}
}
main();
Different browsers shows the stack in different string formats:
Safari : Caller is: main#https://stacksnippets.net/js:14:8
Firefox : Caller is: main#https://stacksnippets.net/js:14:3
Chrome : Caller is: at main (https://stacksnippets.net/js:14:3)
IE Edge : Caller is: at main (https://stacksnippets.net/js:14:3)
IE : Caller is: at main (https://stacksnippets.net/js:14:3)
Most browsers will set the stack with var stack = (new Error()).stack. In Internet Explorer the stack will be undefined - you have to throw a real exception to retrieve the stack.
Conclusion: It's possible to determine "main" is the caller to "Hello" using the stack in the Error object. In fact it will work in cases where the callee / caller approach doesn't work. It will also show you context, i.e. source file and line number. However effort is required to make the solution cross platform.
function Hello() {
alert(Hello.caller);
}
It's safer to use *arguments.callee.caller since arguments.caller is deprecated...
2018 Update
caller is forbidden in strict mode. Here is an alternative using the (non-standard) Error stack.
The following function seems to do the job in Firefox 52 and Chrome 61-71 though its implementation makes a lot of assumptions about the logging format of the two browsers and should be used with caution, given that it throws an exception and possibly executes two regex matchings before being done.
'use strict';
const fnNameMatcher = /([^(]+)#|at ([^(]+) \(/;
function fnName(str) {
const regexResult = fnNameMatcher.exec(str);
return regexResult[1] || regexResult[2];
}
function log(...messages) {
const logLines = (new Error().stack).split('\n');
const callerName = fnName(logLines[1]);
if (callerName !== null) {
if (callerName !== 'log') {
console.log(callerName, 'called log with:', ...messages);
} else {
console.log(fnName(logLines[2]), 'called log with:', ...messages);
}
} else {
console.log(...messages);
}
}
function foo() {
log('hi', 'there');
}
(function main() {
foo();
}());
Try accessing this:
arguments.callee.caller.name
Just console log your error stack. You can then know how are you being called
const hello = () => {
console.log(new Error('I was called').stack)
}
const sello = () => {
hello()
}
sello()
I wanted to add my fiddle here for this:
http://jsfiddle.net/bladnman/EhUm3/
I tested this is chrome, safari and IE (10 and 8). Works fine. There is only 1 function that matters, so if you get scared by the big fiddle, read below.
Note:
There is a fair amount of my own "boilerplate" in this fiddle. You can remove all of that and use split's if you like. It's just an ultra-safe" set of functions I've come to rely on.
There is also a "JSFiddle" template in there that I use for many fiddles to simply quick fiddling.
If you just want the function name and not the code, and want a browser-independent solution, use the following:
var callerFunction = arguments.callee.caller.toString().match(/function ([^\(]+)/)[1];
Note that the above will return an error if there is no caller function as there is no [1] element in the array. To work around, use the below:
var callerFunction = (arguments.callee.caller.toString().match(/function ([^\(]+)/) === null) ? 'Document Object Model': arguments.callee.caller.toString().match(/function ([^\(]+)/)[1], arguments.callee.toString().match(/function ([^\(]+)/)[1]);
Here, everything but the functionname is stripped from caller.toString(), with RegExp.
<!DOCTYPE html>
<meta charset="UTF-8">
<title>Show the callers name</title><!-- This validates as html5! -->
<script>
main();
function main() { Hello(); }
function Hello(){
var name = Hello.caller.toString().replace(/\s\([^#]+$|^[^\s]+\s/g,'');
name = name.replace(/\s/g,'');
if ( typeof window[name] !== 'function' )
alert ("sorry, the type of "+name+" is "+ typeof window[name]);
else
alert ("The name of the "+typeof window[name]+" that called is "+name);
}
</script>
Just want to let you know that on PhoneGap/Android the name doesnt seem to be working. But arguments.callee.caller.toString() will do the trick.
here is a function to get full stacktrace:
function stacktrace() {
var f = stacktrace;
var stack = 'Stack trace:';
while (f) {
stack += '\n' + f.name;
f = f.caller;
}
return stack;
}
Note you can't use Function.caller in Node.js, use caller-id package instead. For example:
var callerId = require('caller-id');
function foo() {
bar();
}
function bar() {
var caller = callerId.getData();
/*
caller = {
typeName: 'Object',
functionName: 'foo',
filePath: '/path/of/this/file.js',
lineNumber: 5,
topLevelFlag: true,
nativeFlag: false,
evalFlag: false
}
*/
}
Works great for me, and you can chose how much you want to go back in the functions:
function getCaller(functionBack= 0) {
const back = functionBack * 2;
const stack = new Error().stack.split('at ');
const stackIndex = stack[3 + back].includes('C:') ? (3 + back) : (4 + back);
const isAsync = stack[stackIndex].includes('async');
let result;
if (isAsync)
result = stack[stackIndex].split(' ')[1].split(' ')[0];
else
result = stack[stackIndex].split(' ')[0];
return result;
}
I could use these in 2021 and get the stack which starts from the caller function :
1. console.trace();
2. console.log((new Error).stack)
// do the same as #2 just with better view
3. console.log((new Error).stack.split("\n"))
Try the following code:
function getStackTrace(){
var f = arguments.callee;
var ret = [];
var item = {};
var iter = 0;
while ( f = f.caller ){
// Initialize
item = {
name: f.name || null,
args: [], // Empty array = no arguments passed
callback: f
};
// Function arguments
if ( f.arguments ){
for ( iter = 0; iter<f.arguments.length; iter++ ){
item.args[iter] = f.arguments[iter];
}
} else {
item.args = null; // null = argument listing not supported
}
ret.push( item );
}
return ret;
}
Worked for me in Firefox-21 and Chromium-25.
Another way around this problem is to simply pass the name of the calling function as a parameter.
For example:
function reformatString(string, callerName) {
if (callerName === "uid") {
string = string.toUpperCase();
}
return string;
}
Now, you could call the function like this:
function uid(){
var myString = "apples";
reformatString(myString, function.name);
}
My example uses a hard coded check of the function name, but you could easily use a switch statement or some other logic to do what you want there.
As far as I know, we have 2 way for this from given sources like this-
arguments.caller
function whoCalled()
{
if (arguments.caller == null)
console.log('I was called from the global scope.');
else
console.log(arguments.caller + ' called me!');
}
Function.caller
function myFunc()
{
if (myFunc.caller == null) {
return 'The function was called from the top!';
}
else
{
return 'This function\'s caller was ' + myFunc.caller;
}
}
Think u have your answer :).
Why all of the solutions above look like a rocket science. Meanwhile, it should not be more complicated than this snippet. All credits to this guy
How do you find out the caller function in JavaScript?
var stackTrace = function() {
var calls = [];
var caller = arguments.callee.caller;
for (var k = 0; k < 10; k++) {
if (caller) {
calls.push(caller);
caller = caller.caller;
}
}
return calls;
};
// when I call this inside specific method I see list of references to source method, obviously, I can add toString() to each call to see only function's content
// [function(), function(data), function(res), function(l), function(a, c), x(a, b, c, d), function(c, e)]
I think the following code piece may be helpful:
window.fnPureLog = function(sStatement, anyVariable) {
if (arguments.length < 1) {
throw new Error('Arguments sStatement and anyVariable are expected');
}
if (typeof sStatement !== 'string') {
throw new Error('The type of sStatement is not match, please use string');
}
var oCallStackTrack = new Error();
console.log(oCallStackTrack.stack.replace('Error', 'Call Stack:'), '\n' + sStatement + ':', anyVariable);
}
Execute the code:
window.fnPureLog = function(sStatement, anyVariable) {
if (arguments.length < 1) {
throw new Error('Arguments sStatement and anyVariable are expected');
}
if (typeof sStatement !== 'string') {
throw new Error('The type of sStatement is not match, please use string');
}
var oCallStackTrack = new Error();
console.log(oCallStackTrack.stack.replace('Error', 'Call Stack:'), '\n' + sStatement + ':', anyVariable);
}
function fnBsnCallStack1() {
fnPureLog('Stock Count', 100)
}
function fnBsnCallStack2() {
fnBsnCallStack1()
}
fnBsnCallStack2();
The log looks like this:
Call Stack:
at window.fnPureLog (<anonymous>:8:27)
at fnBsnCallStack1 (<anonymous>:13:5)
at fnBsnCallStack2 (<anonymous>:17:5)
at <anonymous>:20:1
Stock Count: 100

Javascript testing, node + sinon, testing 'new' calls

I am trying to test a function that looks like so
ContentModel.prototype.fileHandlers = function() {
if (_.isUndefined(this.__cache__.fileHandler)) {
this.__cache__.fileHandlers = new FileHandlers(this.__data__.fileHandlers);
}
return this.__cache__.fileHandlers;
};
to simply check that it caches how I have it set up like so
it("should return cached the second time.", function() {
contentModel = new ContentModel({
fileHandlers: {}
});
var firstTime = contentModel.fileHandlers();
var secondTime = contentModel.fileHandlers();
expect(firstTime).to.equal(secondTime);
});
And getting the errors of :
AssertionError: expected { Object (__data__, __cache__) } to equal { Object (__data__, __cache__) }
+ expected - actual
I just want to basically check the second call is the same - so it's cached when I use the new ContentModel. Can't seem to figure out how to wrestle down this problem. It's sort of an odd problem, but I am going for as much coverage as possible. Thanks!
Just to clarify a little further - I can change .to.equal to to.deep.equal and the test will pass, however I want to check if the object is the same object being returned, not the content.

Custom console log function, a console.log wrapper

function log( msgOrObj ){
if(dev_mode){
console.log({
'message': msgOrObj,
'caller': arguments.callee.caller.toString()
});
}
}
So, I have attempted to write a simple custom console log function (as above). However I am struggling to find which file and line the caller came from. The most I can see is the function that called it.
Has anyone done anything similar? Or is this even possible?
example used in somescript.js from line 70:
log('some very important message!')
Yes but it's very hacky and not cross browser-safe. You can use this as a starting point. It borrows from this answer.
window.trace = function stackTrace() {
var err = new Error();
return err.stack;
}
window.my_log = function (x) {
var line = trace();
var lines = line.split("\n");
console.log(x + " " + lines[2].substring(lines[2].indexOf("("), lines[2].lastIndexOf(")") + 1))
}
window.my_log("What light through yonder window breaks?")
Produces:
What light through yonder window breaks? (<anonymous>:2:42)
The only way I've seen to reliably extract this kind of info is to throw an error and then extract the caller info from the stack trace, something along the lines of:
function log( msgOrObj ){
if(dev_mode){
try {
in_val_id(); // force an error by calling an non-existent method
catch(err) {
// some regex/string manipulation here to extract function name
// line num, etc. from err.stack
var caller = ...
var lineNo = ...
}
console.log({
'message': msgOrObj,
'caller': caller,
'lineNo': lineNo
});
}
}
The stack in Chrome is in this form:
ReferenceError: in_val_id is not defined
at log (<anonymous>:4:13)
at <anonymous>:2:14
at <anonymous>:2:28
at Object.InjectedScript._evaluateOn (<anonymous>:581:39)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:540:52)
at Object.InjectedScript.evaluate (<anonymous>:459:21)
you can extract the function name with:
caller = err.stack.split('\n')[3].split('at ')[1].split(' (')[0];
using a regex here might be more performant. You'll probably need different approaches to extract this info with different browsers.
A word of warning though; throwing and handling errors is expensive so outputting a lot of log messages in this way is likely to impact on general performance, though this may be acceptable if it is specifically for a debug mode
So, this is what I went for in the end (where shout is a bespoke function only running in dev mode):
function log( msgOrObj ){
if(dev_mode){
if( typeof(window.console) != 'undefined' ){
try { invalidfunctionthrowanerrorplease(); }
catch(err) { var logStack = err.stack; }
var fullTrace = logStack.split('\n');
for( var i = 0 ; i < fullTrace.length ; ++i ){
fullTrace[i] = fullTrace[i].replace(/\s+/g, ' ');
}
var caller = fullTrace[1],
callerParts = caller.split('#'),
line = '';
//CHROME & SAFARI
if( callerParts.length == 1 ){
callerParts = fullTrace[2].split('('), caller = false;
//we have an object caller
if( callerParts.length > 1 ){
caller = callerParts[0].replace('at Object.','');
line = callerParts[1].split(':');
line = line[2];
}
//called from outside of an object
else {
callerParts[0] = callerParts[0].replace('at ','');
callerParts = callerParts[0].split(':');
caller = callerParts[0]+callerParts[1];
line = callerParts[2];
}
}
//FIREFOX
else {
var callerParts2 = callerParts[1].split(':');
line = callerParts2.pop();
callerParts[1] = callerParts2.join(':');
caller = (callerParts[0] == '') ? callerParts[1] : callerParts[0];
}
console.log( ' ' );
console.warn( 'Console log: '+ caller + ' ( line '+ line +' )' );
console.log( msgOrObj );
console.log({'Full trace:': fullTrace });
console.log( ' ' );
} else {
shout('This browser does not support console.log!')
}
}
}
log() when declared before the rest of the application can be called anywhere from within the app and give the developer all the information required plus will not run out of dev mode.
(http://webconfiguration.blogspot.co.uk/2013/12/javascript-console-log-wrapper-with.html)
Instead of using arguments you can do
function log( msg ) {
if (dev_mode) {
var e = new Error(msg);
console.log(e.stack);
}
}
This will show you the order in which all the functions were called (including line numbers and files). You can just ignore the first 2 lines of the stack (one will contain the error message and one will contain the log function since you are creating the error object within the function).
If you want a more robust logging - use A proper wrapper for console.log with correct line number? as #DoXicK suggested
I use this in Node and its particularly effective. Console.log is just a function it can be reassigned as well as stored for safe keeping and returned back after we are done. I've no reason to believe this would not work in a browser too.
//Store console.log function in an object so
//we can still use it.
theConsole = {};
theConsole.log = console.log;
//This function is called when console.log occurs
//arguments[0] is what would normally be printed.
console.log = function(){
theConsole.log(">" + arguments[0]);
}
//Call our console.log wrapper
console.log("Testing testing 123");
console.log("Check one two");
//Put back the way it was
console.log = theConsole.log;
console.log("Now normal");
There are a couple options to quickly go about this.
1 - Use console.error
Not very convenient, actual errors will go unnoticed and seeing a lot of red in your console output may have a negative impact on your morale. In short - don't use, unless it's for a very small script or some test
2 - Add your log method to the prototype of Object
to get the current scope/ module name/ etc. Much more flexible and elegant.
Object.prototype.log = function(message){
console.log({
'message': message,
'caller': this,
'stack':arguments.callee.caller.toString()
});
};
Use (anywhere) as:
this.log("foo");
You could add the techniques from this thread to get exact function name inside your object, as so:
var callerFunc = arguments.callee.caller.toString();
callerFuncName = (callerFunc.substring(callerFunc.indexOf("function") + 9, callerFunc.indexOf("(")) || "anoynmous");
Yet make sure your scope is named... forcing you to go from this:
Module.method = function(){}
To this:
Module.method = function method(){}
As for line numbers, calling (new Error()) will give you access to the line number where it was called - and not even on all browsers.
Creating an elegant debugging function is a piece of work
As much as I hate to admit it, the other answer implying reg-exps over a try result seems to be the faster cure for your problem.
It seems you all are struggling too much. I have a simple one-line solution:-
//Just do this, that I have done below: HAVE FUN
var log=console.log;
log(`So this way is known as Aniket's way.`);
log(`Don't be too serious this is just the fun way of doing same thing`);
log(`Thank You`)
Try this
window.log = (() => {
if (dev_mode) {
return console.log;
} else return () => {};
})();

How to get input from Chrome's Javascript console?

Is there a way to programmatically get input from the Javascript Console of Google Chrome, similar to readline() in Firefox?
A tricky way to do this is assigning a getter to a property of a window object
Object.defineProperty(window, 'customCommand', {
get: function() {
console.log("hey");
return "hey";
}
});
So when you type "customCommand" (without parenthesis) it will print your console.log text to the console while the console is "getting" the variable.
You will still have to return something though, and I'm not sure how you could change the order so that the value is returned first and the text in the console appears second. It's definitely possible though, I've seen this happen.
This is an indirect method of taking inputs:
Declare a function in JavaScript:
function your_command_here() {
//code
}
As Chrome's console basically provides methods for communicating with the page's contents, like JavaScript variables, functions, etc., so declaring a function as a receivable command can be an option.
In the console, for providing input, the user shall type:
your_command_here()
Another workaround is:
Declare a function:
function command(var cmnd) {
switch(cmnd) {
case "command1":
//code
break;
}
}
So the user can (more conveniently) type:
command("user's command here")
We can do is hook the console.log so whenever it logs something we can access, otherwise there is no such direct method as like in firefox which does this possible for us in a simple single line code.
var tempStore = [];
var oldLog = console.log;
console.log = function() {
tempStore.push(arguments);
oldLog.apply(console, arguments);
}
You might need to incorporate jsh (Javascript Shell) in your environment if you are working with console IO. See http://code.google.com/p/jsh/ for the how-to. Hope this helps.
Sorry, doesn't work on Chrome JS Console, just works on the repl from repl.it
Example from repl.it:
console.log("Enter your name:");
console.read(function(name) {
console.log('Your name is ' + name + '.');
});
Here is a solution to input from the console.
Try this out!!
process.stdin.resume();
process.stdin.setEncoding('ascii');
var stdInput = "";
var stdInputArr = "";
var index = 0;
process.stdin.on('data', function (data) {
stdInput += data;
});
process.stdin.on('end', function () {
stdInputArr = stdInput.split("\n");
main();
});
// Reads complete line from STDIN
function readLine() {
return stdInputArr[index++];
}
//call this function in the main function
javascript node.js jquery consoleweb
The better you can do is use:
myVar = prompt('Which value do your want?')

Categories

Resources