In Javascript, I can assign a global variable in different data types in different function scope. For example:
var a = 1;
function foo(){
a = a + 10; //a is number in foo
}
function bar(){
a = a + "hello"; //a is string in bar
foo(); //a is string in foo now
}
foo();
bar();
My example is just a simple demo and I believe most Javascript programmers won't write it. However, is there any practical usage for such dynamic feature that global variable changes its data type in different functions?
Dynamic typing allows you to do stuff like this :
var a = false;
if(need to show msg 1){a="message 1"};
if(need to show msg 2){a="message 2"};
if(a){display(a);}
The example is not very good, but the idea is that you can use the same variable as a condition and content, or as an array element and as an error message if what you are looking for is not in the array,...
By the way, when you write a = 1, it is practically equivalent to window.a = 1; global variables can be considered as properties of the window object (.see here for precisions).
So when you write a = a + "hello";, a becomes a string everywhere and not just 'in foo'.
var a = 1; //global variable
In foo() if (1) is defined
function foo(){
a; //In this case a will be global variable and a = 1
}
function foo(){
var a; //In this case a will be private variable, a = undefined but global varibale a not change
}
It depends on what you're trying to do. With Javascript, global variables that are manipulated into different types can be dangerous if you're using a lot of callbacks. Callbacks functions triggering a lot (of course asynchronously) and manipulating a global variable can make it so you end up reading the wrong data in one or more callback functions and an unexpected result will follow deviating from your code's intention.
Related
I'm trying to assign a variable to itself in a function, and if the variable has the same name as an argument to the function it doesn't seem to work, but does if they're not the same name. A code example shows this more clearly.
Is this behavior I should expect? This is a pared down example for my d3 use case which prompted this question. I've shown that below as well.
Non working example
var a;
function assign(a) {
a = a;
}
assign("test")
console.log(a)
undefined
Working Example
var a;
function assign(b) {
a = b;
}
assign("test")
console.log(a)
test
Use case
var data
d3.csv("data.csv", function(error, data) {
//Doesn't work for me
data = data
}
console.log(data)
undefined
In your first example, the argument a that is passed to the function shadows the variable a which is defined outside, so: a=a is assignment of the argument (that was passed to the function) to itself.
In Javascript the scope is functional level scope, so whenever the variable is referenced it is searched for its declaration in the containing scope(function), if it finds it it uses it else it keep searching in prototypical chain upto global scope. So in your case it tries to search a and it founds it as argument a so it stops the search there & uses a from argument.
So to avoid the conflict you have use two ways.
Use the different names
If you want to use the same name then use the explicit scope resolution.
Ex.
var a;
function assign(a) {
Global.a = a //Global is placeholder here for outerscope that variable a is coming from.
}
assign("test")
console.log(a);
Useful links for more clear understanding
Closures
Variable Hoisting
you could use the window object to access the global variable.
var a;
function assign(a) {
window.a = a; // specifying the scope.
};
assign("test")
console.log(a)
More information on 15-common-javascript-gotchas
I'm building reusable function, but I can't change global variables values.
var foo = 5;
function MyFunction(arg) {
setInterval(function(){
foo = 2 + arg;
return foo;
}) ;
}
foo = MyFunction(1);
alert( foo );
After function complete I'm getting undefined;
Thanks in advance.
var foo = 5;
function MyFunction(arg) {
foo = 2 + arg;
}
MyFunction(1);
alert( foo );
You assigned the result of MyFunction invocation to foo and that's why you got undefined. MyFunction has no return statement.
ekuusela gives the right answer as to why your (presumably simplified) example doesn't work.
There are lots of reasons why you could have problems with globals, the most common being that you are accidentally clobbering a global by using the same identifier in some other function, and forgetting to declare it locally. To this day I still get problems where I've written for (i=0;i<n;i++) without first declaring var i in that function-- which then uses a global i, and works fine until 6 months later I make the same mistake somewhere else...
As a useful tip for debugging, the expression var G = (function(){return this})() will always give you the global object, no matter where you run it, including eval'd code. You can then access the global variable foo as G.foo, evaluate ('foo' in G) to check whether such a global exists, and so on.
In order to define a global variable you can use variable name without var keyword or define the variable outside any function scope. Then you can access it by the given method :
foo = 5;
function MyFunction(arg) {
window.foo = 2 + arg;
}
MyFunction(1);
alert( window.foo );
Note: Now foo is a part of window object.
Today I came a cross the self executing functions, than somehow I ended up knowing about
Self-Executing Anonymous Functions, then I've read this article: http://briancrescimanno.com/how-self-executing-anonymous-functions-work/
The thing is that I don't know WHY to use Self-Executing Anonymous Functions because if I need to do something like:
var test = "a";
(function(foo) {
alert(foo);
})(test);
I could just make something like:
var test = "a";
alert(foo);
Or did I miss anything?
also this can be done to any code inside the function, but I used alert() to make simple
Update:
Even thought I've already accepted and answer I would like to share something I've found, if anyone came across this question later :)
Using this notation we can also make an endless loop like following:
(function loop(){
// do something here
loop();
)();
There are a couple of reasons why one would use an IIFE:
1) No littering
var a = 'foo';
alert(a);
vs
(function() {
var a = 'foo';
alert(a);
}())
Both examples do the same thing, but in the second example there is no a variable inside the outer scope.
2) State capturing
var a = 'foo';
window.setTimeout(function() { alert(a); }, 1);
a = 'bar';
vs
var a = 'foo';
window.setTimeout( (function(a_copy) {
return function() { alert(a_copy); }
}(a)), 1);
a = 'bar';
The first example alerts bar, while the second alerts foo. You will find this technique used especially with loops.
Your initial example isn't worth to be executed in an anonymous function, so its a bad example to understand WHY to use this technique. Here is a good example to explore state capturing:
var list = [{id: 1, data: null}, ...];
for (var i = 0; i < list.length; i++) {
(function(item) {
// start async request, for each item in the list, in the order of the list
asyncAjax("get-data-from-somewhere.json?what=" + list[i].id, function (response) {
// thats the on success callback, which gets executed when the server responded
// each item will have different response times, therefore the order of response is various
// if we would use simply list[i].data, it wouldn't work correctly, because "i" would has the value of list.length, because the iteration has been finished yet.
item.data = response;
});
})(list[i]); // the function will preserve the reference to the list item inside, until the function has been fully executed
}
When writing sync. code, you can always fallback to classic object oriented style of structering your code. So you can avoid closures / instant-anonymous function calls. But as soon as you use async. mechanics, closures get very handy and make your code looking more clean, off course only if you can read and understand closures :)
By the way, you could also simply write:
function(private) {}(outer)
is the same as
(function(private) {})(outer)
but the second is better, because its simply more obvious for the reader.
The syntax you describe is commonly referred to as an "immediately invoked function expression", or IIFE.
One of the common use cases is to emulate private variables:
var ns = (function () {
var x = 1; // "private"
return {
getX: function () {
return x;
}
}
}());
ns.getX(); // 1
ns.x; // undefined because x is "private"
In that example the x variable is local to the IIFE. It's not directly accessible outside of it. However, since it is referred to by the getX method, which is accessible outside of the IIFE (because it's part of the returned object) a reference to x is kept alive. This is what is usually meant by the term "closure".
Self executing functions are not really useful if you just do an alert inside.
Consider something like this:
(function(foo) {
var a = ..
// do something with a and foo
})(test);
The advantage here is that a is "private" inside the method and cannot be used outside the method. So a doesn't end up as a global variable and can't be overwritten by some other piece of javascript which uses a variable of the same name.
I've been learning Javascript with Khan Academy. I'm looking at : http://www.khanacademy.org/cs/speed-circles/964929070
there is a line that reads "var draw = function() {...}" is he defining a function called draw? Or is the variable draw calling some function (which I don't see defined)?
Thanks!
Yes, a function expression is being assigned to the variable named draw. You can even call it:
var draw = function() {
console.log('xyz');
};
draw(); // 'xyz'
In JavaScript, functions are objects, just like arrays and -logically- objects are. As you may have found out already these objects can be assigned to a multitude of variables, but as soon as you change one of these variables, they all change. That's because JS always assigns by value, but a variable is never assigned an object directly: it's assigned a reference to an object:
var obj = {iam: 'an object'};
var reassign = obj;
console.log(obj);//shows object
console.log(reassign);//surprize, shows the same thing
reassign.bar = 'foobar';
console.log(obj.bar);//logs foobar, the variable obj has gained the same property, because it is the same object.
The same applies to functions, being objects, the can be assigned to variables/properties all over the place, but it'll still be the same object/function:
var foo = function()
{
console.log('I am an object');
};
var second = foo;
second();//logs I am an object
console.log(second === foo);//logs true, because they both reference the same thing
Why, then, you might ask is an anonymous function being assigned to a variable, instead of just declaring a function as you'd expect? Well:
function foo(){}
is hoisted, prior to running any code, JS moves all function declarations and variable declarations to the very top of the scope, but in your case, you're not simply defining a function, or declaring a variable: JS has to do something, too: assign a reference to a variable. The function won't be hoisted:
var foo = function()
{
console.log('foo');
};
foo();//logs foo
foo = function()
{
console.log('bar');
};
foo();//logs bar now
If foo were undefined prior to the assignment, you'd get an error. If any code preceded the code above, JS would hoist the variable declaration of foo, but it's value would still be undefined.
What's the point? This will prove useful when you start playing with closures, or if you need the function to differ, depending on a branch (if (x){ foo = functionX} else { foo = functionY;}). These are just 2 reasons why you'd want to avoid scope hoisting... but the most important reason of all ATM has to be redefining a function on the fly
Note that in processing.js (as used by this Khan academy demo), the function draw is automatically called every frame reference doc.
This bit of code overrides the default (empty) implementation of draw so that the given code is called every frame.
Khan academy has a tutorial about this use of the draw function here.
function draw(){ return "Sample"; };
var draw = function(){ return "Sample"; };
are same meaning.
function () { ... } creates a function value. That is, something that can be passed around just as easily as a number, or any other object in javascript.
He then binds it to the name draw for future reference.
He could as well have written
function draw() {
...
}
For these purposes they are equivalent.
I'm trying to learn JS on codeacademy and I can't understand/get past this thing. Can someone please provide an answer and also an explanation of why is it so? Would deeply appreciate.
// This function tries to set foo to be the
// value specified.
function setFoo(val) {
// foo is declared in a function. It is not
// accessible outside of the function.
var foo = val;
}
setFoo(10);
// Now that we are outside the function, foo is
// not defined and the program will crash! Fix this
// by moving the declaration of foo outside of the
// function. Make sure that setFoo will still update
// the value of foo.
alert(foo);
You can see scope as a term meaning what variables you can reach at a specific "level" in the code. In JavaScript, these "levels" are defined by functions. Each function introduces a new level.
For example, take this sample code:
var a;
// you can access a at this level
function function1() {
var b;
// you can access a, b at this level
function function2() {
var c;
// you can access a, b, c at this level
}
}
So in your case, you should declare var foo; outside the function, preferably above it. Then you can set it inside setFoo with foo = val;. foo then refers to the one you declared in the level above setFoo.
foo is accessible both in setFoo and in the alert call that way; compare it with the above sample code (function1 is setFoo, a is foo and the alert call is in the top-most level. function2, b and c are not used in your case.).
// Create globale variable
// (You should not use globale variables!)
var foo;
// set value
function setFoo(val) {
foo = val;
}
setFoo(10);
// show value
alert(foo);
Just declare foo outside any function then it will be global:
var foo = null;
function setFoo(val) {
foo = val;
}
setFoo(10);
alert(foo);
Try it !
When you declare a variable in Javascript it is only visible to code that is in the same function as it is declared, or a function inernal to that function. Because foo is originally declared in the SetFoo function nothing outside of SetFoo is able to see it, so the call to alert fails as foo does not exist in the gloabl scope.
As the comments suggest, moving the declaration of foo out of the function and into the global scope (which you can think of as a catch-all function that contains everything) would allow you to use foo when calling alert.
var foo;
function setFoo(val) {
foo = val;
}
setFoo(10);
alert(foo); // No longer crashes
Every function in Javascript has it's own scope. That means that every variable you define there with the var keyword, will only be available within that function. That means that when you call setFoo(10), you create the variable foo, give it a value of five, after which it is immediately destroyed because it went out of scope.
There are multiple ways to solve this problem. The first would be to remove the var keyword. This would put foo in the global scope, which means that it's available everywhere. However, this is discouraged, you want to keep the global scope as uncluttered as possible, so that if you have javascript code provided by multiple people on the same page, they can't overwrite other people's variables. Another way to do it would be this:
function setFoo(val){
var foo = val;
alertfoo = function(){
alert(foo)
}
}
In this example, the only thing you're putting in the global scope is the alertfoo function, because you want that to be available everywhere. The alertfoo function is defined inside the setFoo function, this means that although foo should have gone out of scope after setfoo has been executed, it is kept in memory, because alertfoo has access to it.
This makes for some nice tricks. For example, let's say you're making a javascript library that will be included on other people's pages, you'll want to create a scope inside of which you can define variables, without polluting the global scope. The most common way to do this, is by declairing a self-executing function. This is a function which is executed immediately after being defined, it looks like this:
(function(){
//set variables you want to be global in your own code
var mainpage = document.getElementById('main');
//define functions you want to make available to other people in a way that puts them in the global scope
setMainElement = function(newmain){mainpage = newmain;}
})();
You can make this even better by making only one object global, and provide your interfae through the methods of that object, this way, you create a namespace with all the functions that your library contains. The next example uses an object literal to do this. In javascript, you can create an object by putting key/value pairs petween curly braces. the key/value pairs are properties of the object. for example:
(function(){
var privatevar = 10,otherprivate=20;
publicInterface = {
'addToPrivate': function(x){privatevar+=x;},
'getPrivate': function(){return private}
};
})();
Original code:
function setFoo(val) {
var foo = val;
}
setFoo(10);
alert(foo); // Crash!
Their advice to fix the crash:
Fix this by moving the declaration of foo outside of the function
I'm guessing you're confused as to what they mean by "outside of the function".
Try this edited code:
var foo = 5; // "var" declares the variable to be in this outer scope
function setFoo(val) {
foo = val; // but we can still access it in this inner scope...
}
setFoo(10);
alert(foo); // Displays a dialog box that says "10"
Variables defined in the function is valid only in the function
function setFoo(val) {
foo = val;
}
In JavaScript, new scopes are only created by functions