Other way to write something to the console then console.log - javascript

I working on a project where the console is overwritten:
window.console = {};
window.console['log'] = function() {};
is there another way to write something to the console?
Also other methods, like warn or error are overwritten.
Maybe there is another reference to window.console?

Before overwriting the original console methods, copy it to a different variable:
var OriginalConsole = console;
OriginalConsole.log('test'); //logs test to the console
I'm not sure why you would actually want to overwrite the default console or error functions, but there you have it.

Related

Resetting console.log to it's default functionality

On a live website, I've previously changed console.log to be:
var console = {};
console.log = function () {};
With this code always executing, is it possible to reinstate the console functionality after this code, and if so, how?
It's needed, since the site is live. But I need to do further development, without making any updates to the live site. It's hard without console logging/information.
If that code is not running on the top level, because console is on window, you can just reference window.console.log, eg:
(() => {
var console = {};
console.log = window.console.log;
console.log('foo');
// or, just reference window:
window.console.log('bar');
})();
If the code is running on the top level and you're using const or let (rather than ES5 var), you can do the same thing:
const console = {};
console.log = window.console.log;
console.log('foo');
Otherwise, you'll have to save a reference to console.log before you reassign console with var:
var log = console.log;
var console = {};
console.log = log;
log('foo');
But it's probably not a great idea to create/overwrite built-in global variables like that unless absolutely necessary - the IIFE in the first snippet is probably preferable.
I know this is 1 year and 8 months old by the time I write this, but I happened to figure out a good workaround solution.
You can set a global variable that will get the window.console object when the website loads and another global variable called "console" to get the old console state whenever you want.
var oldConsole = window.console;
var console = {};
So when you need to reset the console to its normal functionality, you simply do:
console = oldConsole.log; // since it's 'window.console.log'
console.log('Hello, world!'); // this output will now display on devtools with its default configuration

Wrapping `console.log` and retaining call stack

In my logging helper class, I have the following:
this.myInfo = console.info.bind(console);
When I call my myInfo function from elsewhere, the calling object and line number are correctly retained and logged in the Chrome devtools.
When I run myInfo though, I also want to run another local function in addition to the console.info. Hence, I figured I could just wrap the above and it would work. I've come up with the following:
var obj = this;
this.myInfo = (function() {
console.info.apply(this, arguments);
myOtherFunc.apply(obj, arguments);
}).bind(console);
The problem is that unlike my first example, I lose the calling context for console.info, and the wrong line number and file are logged in the devTools.
How can I wrap the first example and retain the proper context for the console.info?
You can use getter. In getter you call your other function and then return console.info.bind(console) to caller.
Object.defineProperty(this, "myInfo", { get: function () {
myOtherFunc();
return console.info.bind(console);
}});
In case of passing arguments. You can define following function:
this.myInfo = function()
{
myOtherFunc.apply(null, arguments);
return console.bind.apply(console, arguments);
}
// example of call
this.myInfo(1,2,3)();
I've new solution. You can implement your console.log wrapper in separate JS file or evaluate it with sourceURL then go to Chrome DevTools settings and add "console-wrapper.js" url to blackbox pattern or blackbox this script by link when first message is arrived to console.
When script become blackboxed then all messages will have correct location in source code.
It works in last Google Chrome Canary build and will be available in stable in around two months.
eval("\
function myAwesomeConsoleLogWrapper() {\
console.log.call(console, arguments);\
makeAnotherWork();\
}\
//# sourceURL=console-wrapper.js");
Alexey Kozyatinskiy's approach is cool. However, if not-pretty code like this.myInfo(1,2,3)() is a more serious problem than ugly console output, you could use the wrapper you posted in your question and print needed filename and line number manually having it extracted from new Error().stack. I'd personnaly use Alexey's method unless there was a team working on this project.

How to find if message is already printed to the console

Assume I run my Javascript project in a browser and I'm inside a specific module, can I check whether is already message printed to the console ? i.e. read message from the console...
For example I'm inside my js.file inside function want to check if already printed hello world in the console.
jthanto's answer gave me an idea. I don't think it's good practice, but if you must, you can define your own console class:
var MyConsole = function(oldConsole) {
// store all messages ever logged
this.log = [];
// keep a pointer to oldConsole
this.oldConsole = oldConsole;
}
MyConsole.prototype.log = function(args) {
// push the message into log
this.log.push(Array.prototype.join.call(args));
// call oldConsole.log to actually display the message on the console
if (this.oldConsole)
this.oldConsole.log.apply(this.oldConsole, args);
}
// TODO: implement all other console methods in this fashion (apply for all console API methods)
MyConsole.prototype.<method> = function(args) {
if (this.oldConsole)
this.oldConsole.<method>.apply(this.oldConsole, args);
}
// method to check if something was printed
MyConsole.prototype.wasLogged(message) {
return this.log.indexOf(message)!==-1;
}
// replace console with an instance of MyConsole, pointing to the old console
console = new MyConsole(console);
Save it in a file and load it first (right at the top of your tags)
Use it like:
if (console.wasLogged("Hello World"))
doStuffz();
Hope it helps. Mind it's not tested, but should give you some pointers :)
You could always define your own function for "console.logging" one or more messages (if this is what you are doing), and have a boolean in this function to handle this sort of thing.
I would bet it's not "best practice", but it would solve your problem in some degree.
var messageSent = false;
var myConsoleLog = function($strMessage){
if (!messageSent) {
console.log($strMessage);
messageSent = true;
} else {
// Do whatever you feel like
}
};
Of course if you need to check for more cases you will need to alter the function to actually keep track of more messages. :)
Normally it can't be done. Look at Chrome console's API:
https://developer.chrome.com/devtools/docs/console-api
But this experimental Chrome feature can solve your problem: https://developer.chrome.com/extensions/experimental_devtools_console
Unfortunately it looks like other browsers doesn't have tools like this.

How do I disable console.log when I am not debugging? [duplicate]

This question already has answers here:
How to quickly and conveniently disable all console.log statements in my code?
(38 answers)
Closed 2 years ago.
I have many console.log (or any other console calls) in my code and I would like to use them only
when my app is in some kind of "debug mode".
I can't seem to use some kind of logger function and internally use console.log because then I wouldn't know what line fired it. Maybe only with a try/catch, but my logs are very general and I don't want try/catch in my code.
What would you recommend?
I would probably abuse the short-circuiting nature of JavaScript's logical AND operator and replace instances of:
console.log("Foo.");
With:
DEBUG && console.log("Foo.");
Assuming DEBUG is a global variable that evaluates to true if debugging is enabled.
This strategy avoids neutering console.log(), so you can still call it in release mode if you really have to (e.g. to trace an issue that doesn't occur in debug mode).
Just replace the console.log with an empty function for production.
if (!DEBUG_MODE_ON) {
console = console || {};
console.log = function(){};
}
Clobbering global functions is generally a bad idea.
Instead, you could replace all instances of console.log in your code with LOG, and at the beginning of your code:
var LOG = debug ? console.log.bind(console) : function () {};
This will still show correct line numbers and also preserve the expected console.log function for third party stuff if needed.
Since 2014, I simply use GULP (and recommend everyone to, it's an amazing tool), and I have a package installed which is called stripDebug which does that for you.
(I also use uglify and closureCompiler in production)
Update (June 20, 2019)
There's a Babel Macro that automatically removes all console statements:
https://www.npmjs.com/package/dev-console.macro
One more way to disable console.log in production and keep it in development.
// overriding console.log in production
if(window.location.host.indexOf('localhost:9000') < 0) {
console.log = function(){};
}
You can change your development settings like localhost and port.
This Tiny wrapper override will wrap the original console.log method with a function that has a check inside it, which you can control from the outside, deepening if you want to see console logs and not.
I chose window.allowConsole just as an example flag but in real-life use it would probably be something else. depending on your framework.
(function(cl){
console.log = function(){
if( window.allowConsole )
cl(...arguments);
}
})(console.log)
Usage:
// in development (allow logging)
window.allowConsole = true;
console.log(1,[1,2,3],{a:1});
// in production (disallow logging)
window.allowConsole = false;
console.log(1,[1,2,3],{a:1});
This override should be implement as "high" as possible in the code hierarchy so it would "catch" all logs before then happen. This could be expanded to all the other console methods such as warn, time, dir and so on.
Simple.
Add a little bash script that finds all references to console.log and deletes them.
Make sure that this batch script runs as part of your deployment to production.
Don't shim out console.log as an empty function, that's a waste of computation and space.
This code works for me:
if(console=='undefined' || !console || console==null) {
var console = {
log : function (string) {
// nothing to do here!!
}
}
}
The newest versions of chrome show which line of code in which file fired console.log. If you are looking for a log management system, you can try out logeek it allows you to control which groups of logs you want to see.
// In Development:
var debugMode = true
// In Prod:
var debugMode = false
// This function logs console messages when debugMode is true .
function debugLog(logMessage) {
if (debugMode) {
console.log(logMessage);
}
}
// Use the function instead of console.log
debugLog("This is a debug message");
console can out put not just log but errors warnings etc.
Here is a function to override all console outputs
(function () {
var method;
var noop = function noop() { };
var methods = [
'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
'timeStamp', 'trace', 'warn'
];
var length = methods.length;
var console = (window.console = window.console || {});
while (length--) {
method = methods[length];
console[method] = noop;
}
}());
Refer to detailed post here
https://stapp.space/disable-javascript-console-on-production/

can I load a javascript file under a context other than 'window'?

I try to load some external .js files, and have some irresolvable namespace conflicts.
I had the idea of loading some of the files in their own context somehow, replacing the "this" from pointing at the window object to some custom namespace.
example:
first.js:
name = "first";
second.js:
name = "second";
It seems to me that this kind of trick can be very useful. Is it possible at all?
EDIT
seems that replacing "this" does not begin to solve the problem, as it is not the default context for identifier resolution in javascript. this is my test code:
var first = {};
var second = {};
(function(){name = "first";}).call(first);
(function(){name = "second";}).call(second);
document.write('name= '+name+' <br/>\n'); //prints "second"
document.write('first.name= '+first.name+' <br/>\n'); //prints "undefined"
document.write('second.name= '+second.name+' <br/>\n'); //prints "undefined
any ideas?
RESOLUTION
It is not possible. I ended up wiser than I was this morning, and I gave it up.
I recommend these enlightening reading materials for anyone with a similar problem that might want to take a crack at it:
http://jibbering.com/faq/notes/closures/
http://softwareas.com/cross-domain-communication-with-iframes
One idea I've had for doing it without needing modifications to your external JavaScript file is getting the contents of the JavaScript file in an AJAXy way (up to you how you do that) and then put it all in a function using the new Function(code) way, then initialise that with new:
surrogateWindow = new new Function(jsCode)();
Then surrogateWindow is the this of that code. I think that that idea should work.
I'm not clear on your reason for doing this; what are you using this for, exactly?
Wrapping the contents of your second.js in an anonymous function will prevent variables in that file from conflicting with global variables. If you really must have a this set to a particular object that isn't the global object, you could do something like
var differentThis = {};
(function() {
// Contents of second.js go here
}).call(differentThis);
UPDATE
You can't do what you want. You seem to want to access the Variable object, which is the object to which a property is added when you declare a variable in JavaScript. In global code, the Variable object is the global object, so you can access it; within a function this is a property of the execution context that there is no way to access directly.
Even though this is an old question, this answer may still be relevant for some:
When a js file is loaded it automatically gets the window's context. That is not possible to change.
However, if you are trying to avoid conflicts between libraries that you are loading, and you don't have control over those libs, and they don't have a built-in "no-conflict" mechanism, then there is a nice trick -
you can load those into a source-less iframe.
This will make their context to be the window of the iframe, and you will still be able to access the iframe since there is no cross-domain issue here.
You can see this library as an example for use of this technique.
You can load your file in an iframe, the file is not a .js but an HTML file, like:
<html>
<body>
<script>
var $ = parent.$, // you can share objects with the parent, eg: jQuery
localObject = { // your local object definition
name: 'first',
showName: function(){
$('div.name').html( this.name );
}
};
//assign the local object to the custom namespace
parent.customNamespace.object1 = localObject;
</script>
</body>
</html>
The trick is to use parent. to get the javascript objects available in the parent page.
For the code you've written, I think you're misunderstanding some of the way classes work in JavaScript. In Java you can drop the this., but in JavaScript you can't. You'll always need to have this. there. So then your code becomes:
var first = {};
var second = {};
(function(){this.name = "first";}).call(first);
(function(){this.name = "second";}).call(second);
document.write('name= '+name+' <br/>\n'); //prints "undefined"
document.write('first.name= '+first.name+' <br/>\n'); //prints "first"
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"
It would also be good to do it in a more normal class way. I'm not sure exactly what your situation is as I can't see all your code so you might be already doing it this way.
function Something(name) {
this.name = name;
}
var first = new Something("first");
var second = new Something("second");
document.write('name= '+name+' <br/>\n'); //prints "undefined"
document.write('first.name= '+first.name+' <br/>\n'); //prints "first"
document.write('second.name= '+second.name+' <br/>\n'); //prints "second"
Well you could wrap the contents of the js files with something like this:
var externalInterfaceForYourObject = (function(){
//code that defines your object
//this should refer to the current anonymous function, and not the window object
return this;
})();

Categories