Javascript variable unexpectedly undefined - javascript

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.

Related

Get a variable from Jquery function

This is my config in test.js:
var still;
jQuery(function(still){
still = 5;
});
console.log(still);
i want to show on console the variable 'still' (5), but is show to me 'undefined' !
can any1 help me :) !
Thanks
check this code. remove still from function as argument
var still;
jQuery(function(){
still = 5;
});
console.log(still);
This is because your global still variable has been hidden by function's argument with the same name. Try this:
var still;
jQuery(function(stillTheArgument){
still = 5;
});
console.log(still);
Please, reconsider your code as global variables are often not very good idea.
To prevent clogging the global namespace, alternatively you could pass the variable via immediately invoked function expression like so:
The variable still will be available within the scope of the outer function.
(function($, still) {
$(function() {
alert(still);
});
})(jQuery, "STILL");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
You are overriding the current global variable with your function variable as it currently stands.
as charlietfl told consol statement executed first. and at that time value of still is undefined.
try initializing still like this, no need of onReady handler
var still=5;
console.log(still);

Javascript function implementation

I have code like this :
(function() {
$(document).ready(function() {
//event handlers
$('.project-delete').on('click', function() {
deleteProject($(this));
});
$('.keyword-delete').on('click', function() {
deleteKeyword($(this));
});
this.deleteKeyword = function(model) {
}
}).call(this);
I am curious if this is a good approach since I was learning JS recently and as far as I understand this function will have global scope, doesn't it ? since .call(this) is passing window object to this closure then I think it is not the best option ? Is there something I am missing ? Does changing .call(this) to just () change anything ?
EDIT:So is it OK to just pass window object to that closure ? Wouldn't it better to pass just a empty object or jQuery object ?
Assuming this function is defined in the global scope, the deleteKeyword function will have also have global scope since this in the context of the parent function is basically window (which has been passed in as this from outside; in the global scope this === window).
If you change .call(this) to just (), this is still window inside the function. This is because when you call a function via a simple function-call, this is set to the global object, which is window.
If you want a different value for this, you will need to pass in something else via .call or .apply.
For more information about the behavior of this, take a look here.
"as far as I understand this function will have global scope, doesn't it?"
"Scope" is about what variables a function has access to (i.e., its own local variables, plus locals declared in any functions that it might be nested inside, plus global variables), and that has nothing to do with the value of this. Scope depends on where the function declaration is, but this depends on how the function is called.
"since .call(this) is passing window object to this closure"
We can't tell that just from the code shown. Presumably you mean that that block of code is not nested inside some other function, so then yes, this would be window. But if that code was ever pasted inside some other function then that this might have some other value depending on how that other function was called.
"Does changing .call(this) to just () change anything?"
If you use just () that will mean that inside the function this will be window. Whether that changes anything depends on whether the this in .call(this) was window in the first place - as I already mentioned above, if that block were nested inside some other function this could be something else. Having said that, for the code shown if this was anything other than window I think your code would break. Because you declare a function like this:
this.deleteKeyword = function(model) {...}
...and then inside the second click handler you call what I assume is meant to be the same function without using this:
deleteKeyword($(this));
The only way that will work is if this is window and the deleteKeyword() function is thus global. If this were any other object the function would be a property of that other object and thus not accessible directly as deleteKeyword(). But unless you specifically want deleteKeyword() to be accessible from other code not shown there is no reason to create it as a property of this at all. Just declare it with var:
var deleteKeyword = function(...
...and then it will be accessible only inside that function and the ones nested in it such as your click handler. And the .call() at the end of your function would be redundant since the function wouldn't ever actually use this.
"so isn't it a better option to apply jQuery object (or maybe just empty object) to it to increase performance? Wouldn't it increase performance if this would point to local scope? Since window object is very slow."
Well as I already said, "scope" and the value of this are unrelated concepts. I'm not sure why you are worrying about performance for that code. But if you were to apply jQuery or an empty object with .call(jQuery) or .call({}) the code would not work as explained above.

Explain why anonymous functions in Javascript can access variables in the outer function?

Before I begin, I realize that the ECMA script specification will probably answer my question, but I am asking it on SO in hope of a comprehensible answer.
Take the following code:
function test1(param) {
alert(param);
}
function test2() {
var testvar = 99;
setTimeout(function(){ test1(testvar); }, 1000);
}
test2();
If I run this code, I get a popup box showing 99.
My question is, in test2, shouldn't testvar be null after test2 finishes running? How does the anonymous function in setTimeout get the value of testvar? Is there some sort of stack copying going on right as setTimeout gets called?
This is the result of closures. Functions in JavaScript retain references to -- "close over" -- variables defined in their lexical scope. That is, all variables that can be referenced when the function given to setTimeout is created can be referenced long after test2 has returned.
In this way, a closure is both a function and a set of bindings to the variables that were in scope when the function was created. This is why closures are sometimes called poor man's objects (and vice versa).
This occurs due to Javascript Closures. Essentially, variables available to a function at the time it is defined will always be available to it, no matter where it is called from.
The feature is called closures. You're basically right about what happens, the variables from the surrounding scope get saved if they're needed in an anonymous function.

How to evaluate a variable to access its runtime value in JavaScript?

Ok, I don't know how to actually ask this question without showing it. (Also explains why I can't figure out how to search for it on Google.)
Given the following like of code:
dijit.byId('leftNavigationPane').onLoad = function(){setSecondaryNav(url.secondaryNavId);};
I want the variable url.secondaryNavId to be evaluated, so what I really want is it to be treated something like this:
dijit.byId('leftNavigationPane').onLoad = function(){ setSecondaryNav('item1'); };
I am sure there is probably a better way to do this, so feel free to suggest something.
Don't use eval!
You can use a self-invoking function and closures as follows:
dijit.byId('leftNavigationPane').onLoad = function(id){
return function(){ setSecondaryNav(id); };
}(url.secondaryNavId);
This will execute the outer anonymous function immediately (at runtime), passing the url.secondaryNavId parameter, which will then create a closure that the inner anonymous function will use (so id will always contain the assignment-time value of the url.secondaryNavId property).
There is the JavaScript eval() function.

JavaScript scope and closure

I'm trying to wrap my head around closures (there's a joke in there somewhere) and I ran across this:
(function () { /* do cool stuff */ })();
How does this work? What's the purpose of putting the function in parens? Why the empty parens afterwards?
The point of this is that any variables declared in the cool stuff will not be created in global namespace. Any function in javascript will create such a scope. Suppose you have some javascript you want to run. If you do this:
var b = 1;
// stuff using b
And some other code uses b, it will get your left over value. (Or, even worse, if some other code sets b before your code runs, then tries to get its old value later, you'd have changed it in the meantime.)
On the other hand, if you have this code, which declares and then calls the a function:
function a() {
var b = 1;
}
a();
And some other code later on uses b, it will not see your values, since b is local to the function. The problem with this, of course, is that you're still making a global name - "a", in this case. So, we want a function with no name - this is why you get the code you described. It declares a function with no name, and then calls it.
Unfortunately, you can't just say:
function() { ... }()
because this will be parsed as a function declaration statement, and then a syntax error. By wrapping the function declaration in parenthesis, you get a function expression, which can then be called. You call it like any other function expression (like a, above), using the second set of parens. For example, if the function took arguments, you'd pass them there:
(function(a) { ... })(1)
That creates a function, calls it, and discards it.
It might be clearer if you look at it like this:
var throwaway = function(){
// do cool stuff
};
throwaway();
This is done to create a private namespace. Code in the function can have functions and variables without worrying about conflicting with other code loaded in the page.
i just came across this post recently. This type of function definition & call is called self-invoking functions.
(function(){ //code })();
The code inside the function will be executed immediately upon its definition.
That construct means declare an anonymous function and run it immediately. The reason you put your code inside a function body is because the variables you define inside it remain local to the function and not as global variables. However, they will still be visible to the closures defined inside this function.
The parens around the function make it clear that the function is an expression. The parens after are the call to the function.
Notice that the function does not have a name.
One closures approach is to pass variables to the function:
(function($, var_1, var_2) {
// use JQuery, var_1 and var_2 as local variables
})($, var_1, var_2);
Putting the function declaration inside parens creates an expression which evaluates to the anonymous function within. Therefore, the first parenthetical evaluates to a function.
The "empty parens" at the end invoke the defined function, so "//do cool stuff" executes immediately.
This is a way to execute code on-the-fly while also keeping variables out of the global scope.
What is illustrated here, however, has nothing to do with closures - at least not directly. Closures are about maintaining a lexical scope after a parent function has already exited.

Categories

Resources