Hi I am relatively new to javascript and jQuery and while trying to create a function the runs in intervals of 100 milliseconds I encountered a problem.I seem to get in the console of firebug and error witch says that clasing() is not defined.This is my code:
$(document).ready(function() {
var prev = $("img.selected").prev();
var curent = $("img.selected");
var next = $("img.selected").next().length ? $("img.selected").next() : $("img:first");
$("img").not(":first").css("display","none");
function clasing() {
curent.removeClass("selected");
next.addClass("selected");
}
setInterval("clasing()",100);
});
What am I doing wrong here?Thank you
You have a scope problem. Your variables (prev, curent and next) are accessible inside .ready scope, such as your function clasing. But when you add this function to be called in a interval, using setInterval, this function should be in a Global scope (inside window object). Then, you should declare this function like window.clasing = function(){ ... }, but, doing this, the variables declared in .ready() scope will not be accessible running the function outside this scope, so all your variables must be in a global scope too. This should solve your problem.
However, this isn't a good programming practice, you should declare your variables inside clasing function, then they will be accessible only in function scope; And your function must be delcared outside .ready() function, and then you declare the interval inside .ready() function.
So, your code should be liek this:
function clasing(){
var prev = $("img.selected").prev();
var curent = $("img.selected");
var next = $("img.selected").next().length ? $("img.selected").next() : $("img:first");
curent.removeClass("selected");
next.addClass("selected");
}
$(document).ready(function() {
$("img").not(":first").css("display","none");
setInterval("clasing()",100); //or just setInterval(clasing,100);
});
Change setInterval("clasing()",100); to setInterval(clasing,100);
Change
setInterval("clasing()",100);
To
setInterval(function() {
clasing();
}, 100);
Right now your call to setInterval is running in global scope, but your function is defined inside your jquery function. Creating a closure will give you access to the jquery functions members.
Related
I'm working on a legacy JS script :
!function(e, t) {
var a = function() {
return new a.init
},
......
//end of JS script 1800 lines later
a.init.prototype = a.prototype, e.PDC = a
}(window, jQuery);
i know that ! is a way of declaring an IIFE, but the first variable declaration, i don't understand because the init method of variable a is not declared yet!
The values of variables inside a function aren't looked up until the function is called.
Given return new a.init, it doesn't matter that a is undefined (it is declared) when the function is created, it will be before the function is called.
I have some functions inside of functions and I am having trouble retrieving a variable. It will be easier to show in code I want to log the var three in the testit function but not sure how to do so.
test();
function test(){
var abc;
function one(){
abc = 1;
two();
}
var three;
function two(){
console.log(abc);
three = 2;
testit();
}
one();
}
function testit(){
console.log(three);
two();
}
to make test an object you would do the following:
function test(){
this.abc = 0;
this.three = 0;
this.one();
}
test.prototype.one = function(){
this.abc = 1;
this.two();
}
test.prototype.two = function(){
console.log(this.abc);
this.three = 2;
}
test.prototype.testit = function(){
console.log(this.three);
this.two();
}
and run it like so:
testObj = new test();
testObj.testit();
hope this helps.
edit: BTW: if you put a call in function 'two' back to function 'testit' you'll end up with an infinite loop.
Here's an explanation of what's happening:
When you wrap code in a function, you get what's called function scope. This means that the scope within the function belongs to the function and not to a scope above or outside of it (whichever way you want to look at it).
A closure allows an expression (typically, a function, as MDN states) to have it's own scope while sharing the scope of it's outer or higher scope.
So, let's look at an example:
// This represents the global, or window, scope.
// Analogous to window.outer_var.
var outer_var = 'outer var';
function outer_func() {
// New scope! Local only to outer_func and those
// expressions (functions) *enclosed* by
// `outer_func(){...}, e.g. inner_func(){...}.
var inner_var = 'inner var';
// Only outer_func() or inner-enclosed (to
// inner_func()'s definition) functions can
// access inner_func().
function inner_func() {
// Another new scope! Can access inner_var
// and inner_func_var (below). outer_func()
// canNOT access inner_func_var, though.
var inner_func_var = 'inner func var';
}
}
outer_func(); // Of course, it's in scope and accessible.
inner_func(); // This will cause ReferenceError: inner_func is not defined error.
Simply as it is (no wrapping context, with a closure), var outer_var is created with the global or window scope. It may be accessed in all of the following:
console(window.outer_var);
function outer_func() {console.log(outer_var);}
function inner_func() {console.log(outer_var);} No matter where inner_func's defined.
Here, #2/3 are analogous to:
function outer_func() {console.log(window.outer_var);}
function inner_func() {console.log(window.outer_var);}
Or global this:
function outer_func() {console.log(this.outer_var);}
function inner_func() {console.log(this.outer_var);}
Now, inner_var is accessible from the following:
function outer_func() {console.log(inner_var);}
function inner_func() {console.log(outer_var);} Only from within outer_func().
inner_func() may also only be accessed within outer_func(), because it belongs to the outer_func() scope, and thus is not visible/accessible outside of outer_func()*.
Lastly, inner_func_var is only accessible by:
function inner_func() {console.log(inner_func_var);} Only within outer_func().
To access your three variable, you have three choices:
Make three globally accessible (globals are generally discouraged as they may easily introduce difficult to resolve bugs when one is overwritten by some other code).
Return three from your test() function. In this case the value is accessed, not the actual variable within the function.
Create a property as #logic8 demonstrates, so it may be accessed as a property of an object.
* This isn't entirely true. outer_func() could export a reference to the function out of scope with return inner_func;. This is a more advanced concept, though, and won't be addressed here in depth. Here is an example.
You have to put it in a global to do so:
test();
var three = false;
function test(){
[..]
}
function testit(){
console.log(three);
two();
}
when you declare a variable with var it becomes local to that scope. If you want to access three in both functions, you can either declare it without var (making it global - generally frowned upon for good reasons) or declare it outside of the two functions: var three;
The correct way to do this is by using the closure pattern in javascript. This wraps your javascript class in its own function so anything you declare within that file is only local to your code.
Using jQuery, this is easily accomplished like so:
(function($){
//your code goes here
})(jQuery);
People typically do it this way so their javascript only executes when the page is ready:
$(document).ready(function(){
//your code goes here
});
It's a bit more complicated without jQuery if you want to execute your code when the document is ready:
document.addEventListener('DOMContentLoaded', function(){
console.log('document is ready. I can sleep now');
});
With your code, it would look something like this:
$(document).ready(function(){
var test = function(){
//test code here
};
var one = function(){
//one code here
};
var two = function(){
//two code here
};
var three = function(){
//three code here
};
var testIt = function(){
//test code here
};
});
This way, you can safely access all of your functions from the others without polluting the global namespace.
Being new to JavaScript, I came across a feature in JavaScript where we can write function inside a function which looks cool, but I didn't understand any practical use of it and also how to call the child function?
var parent = "global";
function Parent() {
alert(parent);
function child() {
alert("i am child");
}
}
So, in the above example function parent embeds child function, but I'm not sure on the following 2 questions:
What's the practical use of such syntax / functionality?
How to call child function?
I'm not sure anyone actually gave you the simple answer for what you asked. Defining the child() function inside the Parent() function is just defining a "local" function whose scope is limited to only within the Parent() function's code. It's analogous to a local variable that only exists inside a function.
So, when you have this:
function Parent() {
function child() {
alert("i am child");
}
}
You've created a new function named child which can be called from the code inside of the Parent() function like this:
function Parent() {
function child() {
alert("i am child");
}
child();
}
This function is truly local to within the Parent() function and cannot be called from anywhere else. So, this will not work:
function Parent() {
function child() {
alert("i am child");
}
}
child(); // this function will be undefined
The simplest reason for defining a function this way is just to contain where it can be used and to reduce potential name conflicts. If you couldn't define local functions like this, then all functions would have to be global (or methods on some object) and you'd potentially have a giant set of possible name collisions. This way, you can define functions within a scope that they apply to and they don't potentially collide with any other functions defined similarly within their own scope.
When you get into more advanced uses of javascript, the child() function also has access to all of the variables of its parent. So, you can do this:
function Parent() {
var msg = "Hello!";
function child() {
alert(msg);
}
child(); // will put up an alert that says "Hello!"
}
This allows those local functions to share all the variables from the parent context without having to pass them all to the function. This can be particularly useful when using callbacks because it allows the callbacks to have access to a whole context even though the callback was called by some other code. Here's a simple example of a callback having access to some useful state.
function blink(elem, numTimes, duration) {
var timer, visible = true;
// callback function that is called
function handleInterval() {
// toggle visible state
var val = visible ? "hidden" : "visible";
elem.style.visibility = val;
visible = !visible;
--numTimes;
if (numTimes <= 0) {
clearInterval(timer);
}
}
timer = setInterval(handleInterval, duration);
}
Here you notice that the handleInterval() function has access to not only the local variables from the blink() function, but also the arguments passed to it. This allows us to keep some state going for the setInterval() without using global variables. There's also a more advanced thing going on here called a closure. Closure's can be a bit complicated of a concept, but understanding a couple uses is generally fairly simple.
In this case, the blink() function gets called. It's job is to create an interval timer that, when called will toggle the visibility state of the passed in element. After a certain number of blinks, it will stop the interval timer. But, all the blink function does is call the setInterval() function to schedule the interval timer. It then immediately finishes and is done executing. But, because the setInterval() function has been schedule and it has been passed a reference to the handleInterval() function and that function is in the scope of the blink() function, then all the local variables of the blink() function are "kept alive" and operating even though the blink() function has already finished executing. In fact, these variables will be uniquely kept alive until the timer is stopped and nothing can call handleInterval() any more. If javascript didn't have this capability, then a number of variables in this simple solution would have to be declared as global variables or properties of some object that persists for the duration of this activity. This technique allows the code to much cleaner and self-contained.
Local functions don't have to be named. They can also be anonymous. A more typical way to implement blink() would be like this using an inline anonymous function callback instead of giving it a name:
function blink(elem, numTimes, duration) {
var timer, visible = true;
timer = setInterval(function() {
// toggle visible state
var val = visible ? "hidden" : "visible";
elem.style.visibility = val;
visible = !visible;
--numTimes;
if (numTimes <= 0) {
clearInterval(timer);
}
}, duration);
}
If you're only ever calling this function in one place, then it doesn't really need to be declared separately and given a name. It can, instead be defined inline like this as an anonymous function.
This concept is mainly used in OOJS (Object Oriented JavaScript). Consider the example below:
var Employee=function(ename,eage){
var _name=ename;
var _age=eage;
this.getName=function(){return _name;};
this.getAge=function(){return _age;};
};
var e1=new Employee("Xyz",45);
var e2=new Employee("Abc",23);
e1.getName(); //output=Xyz
e1.getAge(); // output=45
and so on ...
It's a closure which is a way to control scope in JavaScript. Anything defined inside the closure is not visible outside the closure. With a small modification to your function you can call it like so:
var parent = "global";
function Parent(a) {
alert(parent);
function child(b) {
alert(a + b); //child can see both a and b
}
return child;
}
parent(1)(2);
This can be used to implement currying which is explained here Javascript curry - what are the practical applications?
A couple of days ago I have learned on my own example how bad global variables and functions are. So apparently the best solution is NOT to use them, however sooner or later I will need to reuse my variables and functions over and over again.
So my question is: Can I reuse my functions and variables without declaring them globally? Can it be done?
For example, I want to reuse my alertBox function and my containsP variable couple of times:
DEMO: http://jsfiddle.net/ajmyZ/
//I am BAD GLOBAL FUNCTION inside var
//But I am reusable!!!
var alertBox = function () {
alert("Hey I am BAD function!!")
}
$(document).ready(function () {
//I am BAD GLOBAL var
//But I am reusable TOO!!!
var containsP = $("div p:first");
containsP.click(function () {
alert("Hi BAD var HERE!!");
});
$("p").eq(1).click(function () {
alertBox();
});
//I am the NICEST function here
//but I am NOT reusable :(
$("p").eq(2).click(function () {
alert("I am the NICEST function here!!");
});
});
I guess the simplest way to avoid clobbering the global object is just to create your own "application context". You can do that, by creating a self-invoking function which wraps your whole js-code within each file.
(function( win ) {
"use strict";
var still_global_but_only_in_this_anonymous_closure = true;
$(document).ready(function() {
// ...
// accessing the global object:
win.some_global_property = true;
});
}( this ));
Actually, you're already creating such a local context with your anonymous function you pass into .ready(). This is just the more explicit way. That self-invoking method, just calls itself with the global object as argument (where you still can explicitly access global variables). Furthermore, by invoking "use strict"; you're protected from accidently creating global variables alá "Ops_I_Forgot_The_Var_Statment = true;
The code you posted has no global variables. A variable declared inside of a function (in the case of your example, the anonymous document.ready handler) will never be global unless you make one of two mistakes:
forget the var keyword, making an implicit global
explicitly say window.myVar = ...;
I am in a position where I need to "update" a function that exists in another javascript file. The file looks like this:
function jf(){
alert('1');
}
//call jf periodically
jf();
The second js file, which is loaded after looks like this:
console.log(jf);
console.log(window.jf);
var func=function(){
alert('2');
};
jf=func;
window.jf=func;
The first log successfully returns the original jf method, the second doesnt. The first set seems to set the local variable jf, and the second does basically nothing. Is there a way to achieve this functionality?
According to Javascript closures - behavior of overridden functions from the global scope
var done = and function done do basicaly the same thing. They will shadow the outer definition in the inner scope but they will not replace it on the outer scope.
This means you can only override your initial definition of function jf() if you are in the same execution context. Otherwise, replace function jf(){ ... with window.jf = function(){...
Also, running your tests in an inspector console might help.
First, use variables:
var jf = function () {
alert('1');
};
jf();
Then the second bit should work fine:
var func = function () {
alert('2');
};
jf = func;
jf();