I can call a function directly (I'll use alert as an example) like so
alert("Hello World!"); // pops up an alert window
However, when I put a function in an object, calling it no longer works:
d = {func: alert};
d.func("Hello World!"); // doesn't do anything
d["func"]("Hello World!"); // also doesn't do anything
I figured maybe I needed to explicitly pass in a blank this argument, so I tried
d.func(null, "Hello World!") // still nothing
but to no avail. Interestingly, this does work
d.func.apply(null, ["Hello World!"]); // success!
but that's so gratuitously verbose it makes my teeth hurt (to quote JWZ). Is there a more concise, less ugly way?
Functions in JavaScript are passed by value. The alert() function is natively implemented, meaning it has no JavaScript value. Depending on your browser, the meaninfulness (forgive me for that) of that native wrapper varies. Your code actually works in Google Chrome, but won't work in Firefox, and off the top of my head I'm going to say it won't work in Internet Explorer, either, which is generally not friendly about modifying native objects and functions. You could use the following instead:
d = {
func: function (message) {
alert(message);
}
};
If you try this:
function test(x) {
alert(x);
}
var x = {func: test}
x.func('Hi!');
It works as you expect. When I try doing this to alert directly Firebug gives me the following error message:
[Exception... "Cannot modify properties of a WrappedNative"
nsresult: "0x80570034 (NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN)"
location: "JS frame :: http://stackoverflow.com/questions/859466/javascript-function-in-an-object-hash :: anonymous :: line 72" data: no]
So I am guessing it's a security thing or something to do with it being a native function.
I've always done it like this:
var d = Object;
d.hello = function(msg) {
alert(msg)
};
d.hello('hello');
Of course, you can also use PrototypeJS to get all object oriented:
var Message = Class.create( {
display: function(msg) {
alert(msg);
}
});
var msg = new Message();
msg.display('hello');
Related
var test = function(msg) {
alert(msg)
};
(new test("hi")).run();
(new test("hello")).run();
When I run above javascript code, I am able to get alert "hi". But alert "hello" is not coming up.
Anybody can explain what is above, I am completely new to this. Only I know is that "test" is a function
What is run() method does?, because when I removed run in the above code, I am able to see both alerts, pls help...
var test = function(msg) {
alert(msg)
};
(new test("hi"));
(new test("hello"));
Simple, there is no run function, when your code runs (new test("hi")).run() it runs the (new test("hi")) part first, and then errors on the run so the second line is never executed.
If you want to call a function, call it:
test("hi");
Don't run functions (that are not constructors) as constructors. Here is what new does.
"run" is not a defined function.
Even if you replace "run" by "xyz"|| "abc" or any other random function name which is not defined, the code above will work in the same way.
var test = function(msg) {
alert(msg)
};
/** test("hi") getting called, then xyz() throws a javascript error **/
(new test("hi")).xyz();
/** No Execution as there was an error on previous line **/
(new test("hello")).xyz();
Its's just that initially the "test" function is called once and when it encounters a .run() which is not defined, it throws an error and execution stops.
Couldn't you use a find & Replace routine to read the cookie and then replace it with ''?
I have not been able to delete all path cookies using all of the tips above and am still playing with it, but I did make a bookmarklet to extract all the cookies and put them in an iframe so that you can copy&paste them.
javascript: var c=document.cookie;if (c==''){alert('This site didn\'t give you any cookies at all.\nNot a single one!');}else{w=window.open('','Links','scrollbars,resizable,width=400,height=600');w.document.write(c); }
I would like to pass errors to an alert to warn the user they made mistake in their code even if they don't have console open.
var doc=(frame.contentWindow.document || obj.contentDocument|| obj.contentWindow);
var head = doc.getElementsByTagName('head')[0];
var scriptElement = doc.createElement('script');
scriptElement.setAttribute('type', 'text/javascript');
scriptElement.text = scripts;
try{
head.appendChild(scriptElement);
}
catch(e){ alert("error:"+e.message +" linenumber:"+e.lineNumber);}
The appendChild throws an error when the scripts contain an error. It goes straight to the console though, and I want it to display in an alert, because it is for kids and they might not check the console. The try catch block does not catch the error.
I tried it with eval(scripts).
try{
eval(scripts);} catch(e){ alert("error:"+e.message +" linenumber:"+e.lineNumber);}
this does work but it means that the code is executed twice, and that is very inconvenient in some cases.
I tried monkey patching the console.error:
console.log=function(){alert("taking over the log");}
console.error=function(){alert("taking over the log");}
but that only works when I literally use console.error. Not when an actual error is thrown.
What function sends the error to the console in the case of a real error,if it isn't console.error? and can I access it and change it?
Any ideas? Help would be really appreciated.
Thanks Jenita
Whilst try ... catch will work on the code that the script runs initially, as Jenita says it won't catch Syntax Errors, and also it won't catch errors thrown by callback functions which execute later (long after the try-catch has finished). That means no errors from any functions passed to setTimeout or addEventListener.
However, you can try a different approach. Register an error listener on the window.
window.addEventListener("error", handleError, true);
function handleError(evt) {
if (evt.message) { // Chrome sometimes provides this
alert("error: "+evt.message +" at linenumber: "+evt.lineno+" of file: "+evt.filename);
} else {
alert("error: "+evt.type+" from element: "+(evt.srcElement || evt.target));
}
}
This will be called when an exception is thrown from a callback function. But it will also trigger on general DOM errors such as images failing to load, which you may not be interested in.
It should also fire on Syntax Errors but only if it was able to run first so you should put it in a separate script from the one that may contain typos! (A Syntax Error later in a script will prevent valid lines at the top of the same script from running.)
Unfortunately, I never found a way to get a line number from the evt in Firefox. (Edit: Poke around, I think it might be there now.)
I discovered this when trying to write FastJSLogger, an in-page logger I used back when the browser devtools were somewhat slow.
Desperate to catch line numbers, I started to experiment with wrappers for setTimeout and addEventListener that would re-introduce try-catch around those calls. For example:
var realAddEventListener = HTMLElement.prototype.addEventListener;
HTMLElement.prototype.addEventListener = function(type,handler,capture,other){
var newHandler = function(evt) {
try {
return handler.apply(this,arguments);
} catch (e) {
alert("error handling "+type+" event:"+e.message +" linenumber:"+e.lineNumber);
}
};
realAddEventListener.call(this,type,newHandler,capture,other);
};
Obviously this should be done before any event listeners are registered, and possibly even before libraries like jQuery are loaded, to prevent them from grabbing a reference to the real addEventListener before we have been able to replace it.
Ok so the less elegant but highly efficient way of doing this is 'refactoring' your innate console functions. Basically any error or warnings you get are being outputted there by a javascript function that is pretty similar to the familiar console.log() function. The functions that I am talking about are console.warn(), console.info() and console.error(). now let's 're-map' what each of those do:
//remap console to some other output
var console = (function(oldCons){
return {
log: function(text){
oldCons.log(text);
//custom code here to be using the 'text' variable
//for example: var content = text;
//document.getElementById(id).innerHTML = content
},
info: function (text) {
oldCons.info(text);
//custom code here to be using the 'text' variable
},
warn: function (text) {
oldCons.warn(text);
//custom code here to be using the 'text' variable
},
error: function (text) {
oldCons.error(text);
//custom code here to be using the 'text' variable
}
};
}(window.console));
//Then redefine the old console
window.console = console;
Now, generally I would highly advise against using something like this into production and limit it to debugging purposes, but since you are trying to develop a functionality that shows the output of the console, the lines are blurry there, so I'll leave it up to you.
You could wrap the script in its own try/catch, something like:
var doc=(frame.contentWindow.document || obj.contentDocument|| obj.contentWindow);
var head = doc.getElementsByTagName('head')[0];
var scriptElement = doc.createElement('script');
scriptElement.setAttribute('type', 'text/javascript');
scriptElement.text = "try{"+scripts+"}catch(e){console.error(e);alert('Found this error: ' + e +'. Check the console.')}"
head.appendChild(scriptElement);
I encountered a strange error today.
When I invoked the below function in chrome, I got:
var t = function(i){console.log(i);console.log(eval("i"));};
t("123");
//the result in chrome
123
undefined
But the above code invoked in firefox, it came out just as I thought: the second log statement was the same as the first.
In my opinion,the eval statement will use the context of the anonymous function as its runtime context, which contains the parameters.
I didn't find any material involve eval context and parameter.
Can anyone tell me why ?
Actually,I used tempo.js to render html and came out a similar question as I listed above.
the source code is here:
_replaceVariables: function (renderer, _tempo, i, str) {
return str.replace(this.varRegex, function (match, variable, args) {
try {
...
if (variable === '.') {
val = eval('i');
} else if (utils.typeOf(i) === 'array') {
val = eval('i' + variable);
} else {
val = eval('i.' + variable);
}
.....
} catch (err) {
console.log(err);
}
return '';
});
},
When run in chrome,the eval statement got error like this:
TypeError: Cannot convert null to object
I can't figure out why this happened, so I tried the code at the beginning.
The Chrome console implementation of the console functions involves some asynchronous behavior that causes weird issues like what you've discovered.
That said, in your particular case my Chrome logs "123" twice. I find it generally to be a really good idea to augment debugging output with some unique identifying text:
var t = function(i){console.log("param is " + i);console.log("eval result is " + eval("i"));};
The Chrome console output collapses repeated lines and prefixes them with a little circled counter:
(source: gutfullofbeer.net)
That little "2" before "123" means it was logged twice.
I saw many posts how to replace the JS console functions by others but no one leaves it intact for Firebug.
When I replace any of them, it calls my custom function but it reports the message from the very same place the new function comes from.
The goal here is to receive any of those console messages and display them somewhere else whilst I still can jump to the callee in the Firebug console.
Is this possible at all ?
Update :
for instance (PSEUDO) :
//keep the old one
var oriFn=console.error;
console.error=function(){
someOtherFunc(arguments);//send to server for instance
oriFn(arguments);
}
Now somewhere else I'd like to call as usual console.error('bla'); In the Firebug console, it prints my message but shows a link to the replacement code above. I want in the Firebug console the link to the callee's parent function and that's it.
Use a function pointer. Given foo.js:
function foo()
{
console.error = console.log; //Reassign console.error
location.hash = document.title; //Do something
console.error("Not the mama"); //Outputs line foo.js:5
}
References
How to de-anonymize your anonymous functions
JavaScript Wikibook: Anonymous Functions
JavaScript Anonymous Functions
Javascript function declarations vs function operators
I'm developing a complex website that heavily leverages jQuery and a number of scripts. On load of the site, none of my scripting is working (though I can confirm that other scripts are functioning fine). I wouldn't be posting such a lame question here on SE except for one thing:
The instant I hit F12 to turn on developer tools so I can debug my issue, everything instantly works perfectly!
Worse, if I shut down the browser, start it up, turn on Dev Tools first and visit the site, everything works as expected.
So I can't even debug the darned problem because Dev Tools fixes it! What could Dev Tools be doing that makes things work? Does it change the UA (I do some jQuery.browser detection)? Does it do something to doctype?
EDIT
All my console logging is wrapped in the following wrapper utility function:
function log(msg){
if (console){
console.log(msg);
}
}
Any thoughts or suggestions I could try would be welcome. I'll post here if I find a solution.
I appreciate I'm pretty late to the party here, but I've got a solution for IE9 that's a little different.
(function() {
var temp_log = [];
function log() {
if (console && console.log) {
for (var i = 0; i < temp_log.length; i++) {
console.log.call(window, temp_log[i]);
}
console.log.call(window, arguments);
} else {
temp_log.push(arguments);
}
}
})();
Basically instead of console.log you use log. If console.log exists then it works as normal, otherwise it stores log entries in an array and outputs them on the next log where the console is available.
It would be nice if it pushed the data as soon as the console is available, but this is less expensive than setting up a custom setInterval listener.
Updated function (1 October 2012)
I've updated this script for my own use and thought I'd share it. It has a few worthy improvements:
use console.log() like normal, i.e. no longer need to use non-standard log()
supports multiple arguments, e.g. console.log('foo', 'bar')
you can also use console.error, console.warn and console.info (though outputs them as console.log)
script checks for native console every 1000ms and outputs the buffer when found
I think with these improvements, this has become a pretty solid shim for IE9. Check out the GitHub repo here.
if (!window.console) (function() {
var __console, Console;
Console = function() {
var check = setInterval(function() {
var f;
if (window.console && console.log && !console.__buffer) {
clearInterval(check);
f = (Function.prototype.bind) ? Function.prototype.bind.call(console.log, console) : console.log;
for (var i = 0; i < __console.__buffer.length; i++) f.apply(console, __console.__buffer[i]);
}
}, 1000);
function log() {
this.__buffer.push(arguments);
}
this.log = log;
this.error = log;
this.warn = log;
this.info = log;
this.__buffer = [];
};
__console = window.console = new Console();
})();
You have console calls, in IE these will fail if the dev tools are not open. A simple fix is to wrap any console calls in a function like:
function log(msg) {
if(console)
console.log(msg);
}
I have hacked it the following way
<script type="text/javascript">
(function () {
if (typeof console == "undefined") {
console = {
log : function () {}
}
}
})();
</script>
And this is the first script element in the .
Most of the other solutions should work great, but here's a short one liner if you don't care about catching log messages if the console is not available.
// Stub hack to prevent errors in IE
console = window.console || { log: function() {} };
This lets you still use the native console.log function directly still instead of wrapping it with anything or having a conditional each time.
I find it much more convenient to simply use console && console.log('foo', 'bar', 'baz') rather than use a wrapper function.
The code you provided:
function logError(msg){
if (console) {
console.log(msg);
} else {
throw new Error(msg);
}
}
Will produce an error for IE when dev tools are closed because console will be undefined.
The console.log wrapper that I used was not sufficient to detect the console in IE9. Here's the wrapper that works from a related question on SE:
function logError(msg){
try {
console.log(msg);
} catch (error) {
throw new Error(msg);
}
}
function log(msg){
try {
console.log(msg);
} catch (error) { }
}
A proper test for the availability of the console object would be:
if (typeof console === "undefined" || typeof console.log === "undefined")
If you have multiple parallel script files, maybe the files are being loaded/executed in a different order with developer tools on/off.
I have run into this issue many times. Basically with variables we do this to check if they are valid
var somevar;
if (somevar)
//do code
this works because somevar will resolve to undefined. But if your checking a window property for example. window.console.
if (console) <---- this throws an exception
You cannot do the same check. The browser treats it differently. Basically only doing this
if (window.console) <---- will NOT throw an exception if undefined
//some code
this will work the same as the first example. So you need to change your code to
function log(msg){
if (window.console){
console.log(msg);
}
}