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
Related
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.
I have a problem. I have defined some global variables and namespaced it into an object called "app".
Example:
window.app : {
foo : null,
bar : null,
}
Well, the idea is that I want to be able to modify those variables from any module by calling app.foo = "baz" or app.bar = "baz", but I don't want the user to be able to modify those variables from the browser console (element inspector).
Is it possible?
PD: Well, I have a Backbone.js collection which is sinchronized with the server. I don't want the user to be able to modify that collection with the console
No. The browser is the user's domain. They have the possibility to modify your scripts and inject their own functionality in various ways (through the console or browser plug-ins). That's one of the reasons why you should never blindly trust user input on the server side.
They could even manually forge a complete request, tricking your server into thinking that your JavaScript code made that request.
If you want these values to be secure, you need to keep them on the server. You can send them to the client, of course, as long as you keep a possibility to validate the values against those on the server.
The only way to make the variables not (easily) modifiable by a user is to remove them from global scope - something like
!function() {
foo = null;
bar = null;
}()
You'll need to redesign the way your modules interact with each other to accomplish this. An MVC Framework like Angular.js will help.
You should never rely on this as a security mechanism, though - the browser is fully in the user's control.
Still for them who are searching solution to this problem, use const modifier while assigning variable instead of var. Now try to change value of variable from browser console. It will throw error Uncaught TypeError: Assignment to constant variable that will prevent your data from being modified.
A possible way to avoid to (easily) modify javascript variables from the browser console is to either use the get operator (ECMAScript 5) or a getter-function.
To make it possible to define "private" variables, an anonymous function defines the variables in the local scope, so that it is not globally available. (as mentioned in joews' answer)
As mentioned before, this does not make it impossible to manipulate the variables.
Via get operator:
window.app = (function () {
var _foo = 123; // private variable
return {
get foo () { return _foo; }
};
}());
// --- accessing app from the console ---
// app.foo is readable from console, but not modifiable
console.log(app.foo);
app.foo = 234;
console.log(app.foo); // 123
// However, app.foo can still be modified via Object.defineProperty or
// removed with the delete operator
Via getter-function (older browsers, e.g IE < 9):
window.app = (function () {
var _foo = 123; // private variable
return {
foo: function() { return _foo; }
};
}());
// --- accessing app from the console ---
console.log(app.foo()); // 123
// However, the foo function can still be overwritten.
// But at least, the internal _foo variable is unaffected.
app.foo = function () { return 234; }
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.
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/
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;
})();