If I just do changeImage(); it works fine, but I can't figure out how to get setInterval() to work. Here's my code:
HTML:
<div id="coin1"></div>
JS:
$(document).ready(function() {
function changeImage() {
if ($("#coin1").css("display") == "none") {
$("#coin1").fadeIn("slow");
} else {
$("#coin1").fadeOut("slow");
}
};
setInterval("changeImage()", 2000);
});
Because you're defining changeImage() within $(document).ready(), it isn't defined globally and therefore won't be called by setInterval. Use the function's name instead, i.e.:
setInterval(changeImage, 2000);
Hope this helps.
Just to be crystal clear, as the accepted answer does show the correct code but the explanation is incorrect, the issue is not that:
...you're defining changeImage() within $(document).ready()...
It is completely fine for you to define functions within the scope of $(document).ready().
The issue is that you're passing a string – setInterval("changeImage()", 2000); – as the first parameter to setInterval() instead of a function to be used as the callback. Per the accepted answer's code (but not explanation), the proper way to use setInterval() is like setInterval(changeImage, 2000);. Notice that parentheses are not used here. This is because you want to pass the function itself as the parameter, not whatever is returned by the function when it's called.
The only reason the code you're using happens to work when you move it outside of the scope of $(document).ready() is because when you do pass a string, the interpreter is forced to run an eval() against the string, and the eval() is happening in the global scope.
So while it is possible to have the solution work with a string, it is not good coding. Per the docs for setInterval():
An optional syntax allows you to include a string instead of a function, which is compiled and executed every delay milliseconds. This syntax is not recommended for the same reasons that make using eval() a security risk.
Related
So I had an interview where I was asking the purpose of declaring and calling a function immideately, and i couldn't answer it, i.e:
(function(){
// code
})();
What's the reason for doing this?
Object-Oriented JavaScript - Second Edition: One good application of immediate (self-invoking) anonymous functions
is when you want to have some work done without creating extra global
variables. A drawback, of course, is that you cannot execute the same
function twice. This makes immediate functions best suited for one-off
or initialization tasks.
The syntax may look a little scary at first, but all you do is simply
place a function expression inside parentheses followed by another set
of parentheses. The second set says "execute now" and is also the
place to put any arguments that your anonymous function might accept:
(function() {
})();
or
(function() {
}());
are the same:
For this block of code:
if(!skipit)
{
var update_argument='';
if (document.formname.fieldname)
{
update_argument=document.formname.fieldname[document.formname.fieldname.selectedIndex].value;
}
window.setTimeout('updatepcols(update_argument)',250);
return false;
}
I was getting an error in my setTimeout call that "update_argument" was undefined. When I changed the line where I assign it the null string value from "var " to "window.", the error was gone and the code worked. I would guess that there's a scope issue here, but I don't follow it. Why would update_argument be undefined in this case, but putting it in the window object lets me use it? (updatepcols is a function that updates pricing columns.)
Try this instead. Using a closure in this fashion preserves the reference to update_argument
setTimeout(function(){
updatepcols(update_argument);
},250);
I have a funny feeling the script you passed as text, when evaluated, executes in the global scope, i.e. outside the local scope in which update_argument is declared.
setTimeout('updatepcols(update_argument)',250);
I'm not sure if this is a scope issue or not, but altering your setTimeout call should do the trick:
window.setTimeout('updatepcols('+update_argument+')',250);
This fiddle demonstrates: http://jsfiddle.net/mLrqZ/
Change your expression. Should be written like this if you want to pass the local variable to your callback function:
window.setTimeout('updatepcols('+update_argument+')', 250);
or if you want to use a closure instead, then do this:
window.setTimeout(function(){ updatepcols(update_argument) }, 250);
Yeah, like the others say, using a closure is better practice.
I am a newbie to java script and currently reading John Resig's Pro javascript techniques . While explaining closure he refers to calls like setTimeout("otherFunction()",2000) as instances where new JS developers have problems . I could not understand why this is a problem ? Can some one explain please ?In this http://www.w3schools.com/js/js_timing.asp I am seeing a call like var t=setTimeout("alertMsg()",3000); which looks similar to me .
It's not "wrong", it's just not necessarily "right", and it's certainly not recommended.
The setTimeout() function's first parameter can be a string or a function reference / function expression.
If you pass a string it will be slower because effectively you are doing an eval() which is not recommended. More important than speed though is that the scope in which the code in the string executes may not be what you are expecting (and may not be the same in different browsers).
By passing a function reference / function expression instead these problems can be avoided.
The "right" syntax for your example is:
setTimeout(otherFunction, 2000);
Note there are no parentheses after otherFunction - if there were it would call otherFunction() immediately and pass the return value from that function to setTimeout().
If you need to pass parameters to your function you can wrap it in an anonymous function:
setTimeout(function() {
otherFunction(param1, param2);
}, 2000);
That may seem kind of clunky compared to setTimeout("otherFunction(param1,param2)", 2000) but again it avoids issues with scope of where otherFunction, param1 and param2 are defined.
The recommended approach is to use the following:
setTimeout(otherFunction, 2000);
or a closure:
setTimeout(function() {
otherFunction();
}, 2000);
Do not use the overload which takes a string as first parameter because the javascript interpreter will need to parse this string into javascript code.
And yeah, the site you have linked to http://www.w3schools.com is probably one of the worst sites out there to learn programming. It shows exactly what you shouldn't do.
Because it has to eval otherFunction() (and hence spawn a new instance of the interpreter) every time. If you provide a reference to the function, setTimeout can execute it without the necessity to spawn a new interpreter.
So use:
setTimeout(otherFunction,2000);
Anything enclosed with "" is a string so a JavaScript interpreter will generally need to parse the string.
Parsing the string is unnecessary even if it works.
If we simply use
setTimeout(alertMsg,3000);,
the interpreter is not required to do any additional (unnecessary) work, resulting in better code.
Instead of setTimeout("otherFunction()",2000), pass the function directly by doing
setTimeout(otherFunction,2000) is much better. The previous way has to do eval the string "otherFunction()".
It's not the first time I've used setTimeout(), but I can't figure out what the problem is. The code part of the setTimeout() is executing correctly, but it is executing immediately without the delay. If anyone can see the problem, that would help. Here's the code:
if(token==1){
img1.src=ssImages[imgNum];
num1=0;
num2=10;
setTimeout('crossFade()',2500);
}
Are you sure this is the code? If it executes immediately there are usually two reasons:
The developer thought the time is specified in seconds - but 2500 is fine, that's 2.5 seconds.
He calls the function immediately (e.g. setTimeout(foo(), 1234));
But none of the reasons apply to your code so check the rest of the code if there are any other calls to that function.
Anyway, you should really pass a function instead of a string:
setTimeout(crossFade, 2500);
Or, if you need to specify any arguments:
setTimeout(function() {
crossFade(...);
}, 2500);
I agree with Theifmaster. The window. setTimeout method takes two arguments:
1) Function OR Expression
2) Time in ms
In your code you provide a string or an Expression :
setTimeout('crossFade()',....)
This is generally discouraged as with the use of eval. You should pass a function - either named:
setTimeout(crossFade,....)
OR as suggested anonymous:
setTimeout(function(){crossFade()},....
This is about all you can do to trouble shoot this code unless you provide an example ok jsfiddle for us to see the context this is called.
Can someone please explain the differences between the following functions:
(function($){
// can do something like
$.fn.function_name = function(x){};
})(jQuery);
Could I use jQuery in the next function?
(function(){
}());
And is the following the same as jquery.ready()?
$(function(){
});
Thanks!
(function($){
// can do something like
$.fn.function_name = function(x){};
})(jQuery);
That is self-executing anonymous function that uses $ in argument so that you can use it ($) instead of jQuery inside that function and without the fear of conflicting with other libraries because in other libraries too $ has special meaning. That pattern is especially useful when writing jQuery plugins.
You can write any character there instead of $ too:
(function(j){
// can do something like
j.fn.function_name = function(x){};
})(jQuery);
Here j will automatically catch up jQuery specified at the end (jQuery). Or you can leave out the argument completely but then you will have to use jQuery keyword all around instead of $ with no fear of collision still. So $ is wrapped in the argument for short-hand so that you can write $ instead of jQuery all around inside that function.
(function(){
}());
That is self-executing anonymous function again but with no arguments and runs/calls itself because of () at the end.
That patterns turns out to be extremely useful in some situations. For example, let's say you want to run a piece of code after 500 milli seconds each time, you would naturally go for setInterval.
setInterval(doStuff, 500);
But what if doStuff function takes more than 500 mill-seconds to do what it is doing? You would witness unexpected results but setInterval will keep on calling that function again and again at specified time irrespective of whether doStuff finished.
That is where that pattern comes in and you can do the same thing with setTimeout in combination with self-executing anonymous function and avoid bad setInterval like this:
(function foo(){
doStuff;
setTimeout(foo, 500);
})()
This code will also repeat itself again and again with one difference. setTimeout will never get triggered unless doStuff is finished. A much better approach than using bad setInterval.
You can test it here.
Note that you can also write self-executing anonymous function like this:
function(){
// some code
}();
Using extra braces around (like before function keyword) is simply coding convention and can be seen in Crackford's writings, jQuery and elsewhere.
$(function(){
});
That is short-hand syntax for ready handler:
$(document).ready(function(){
});
More Information:
How Self-Executing Anonymous Functions Work
I know that this question is old, but I stumbled upon it right now and so may other people. I just wanted to point out that, although Sarfraz's answer is great, it has to be said that no, writing a self-executing, anonymous function within braces is not a coding convention.
function(){
// some code
}();
Will not work and give out a SyntaxError because the function is being parsed as a FunctionDeclaration, and the function name is not optional in this case.
On the other hand, the Grouping Operator makes sure that the content is evaluated as a FunctionExpression.
See: Explain JavaScript's encapsulated anonymous function syntax