global and local variable execution context in javascript - javascript

Trying to understand fundamentals of javascript I ran into a following code and expected value of variable named "foo" would be 7 and 5 however it came out as 7 and 7. Not sure why....
var foo = 5;
(function Test() {
foo = 7;
console.log("foo=" + foo);
})();
console.log("foo=" + foo);
foo=7
foo=7

Because when you do foo = 7; it makes a global variable and sets it to 7, even after the function is done it's still 7. You probably want it to be a local variable:
(function Test() {
var foo = 7;
console.log("foo=" + foo);
})();

To get 7 and 5, you need to put "var" before "foo = 7;" in your function in order to keep it from overwriting the the global foo you declared outside the function.
That is, you need to use var when declaring variables within functions to make them locally scoped to the function.

You are declaring a global variable and then referencing it inside your function. if you want a local variable, declare it inside your function using the var keyword.
//foo variable definition here
var foo = 5;
(function Test() {
//Referencing the already globally defined var.
//Use var foo = 7 in order to define a new local var.
foo = 7;
console.log("foo=" + foo);
})();
console.log("foo=" + foo);

Referencing a global variable inside an immediately called anonymous method doesn't mean it overrides the variable in the global scope!
Something like foo=7 will create a new variable only if there is no other foo that is accessible from the current scope. Which in this case exists!
Immediately called Anonymous function is not a completely isolated scope. As a function, it has a local scope, which is not available outside the block. But it still have access to the global scope.

Related

In javascript, are functions added to scope like variables are? [duplicate]

The var keyword in javascript causes a variable to be stored in the local scope. Without var variables belong to the global scope. What about functions? It's clear what happens when functions are declared like variables
var foo = function() {...}
but what scope does
function foo() {...}
belong to?
EDIT:
I realized I didn't ask quite the right question so as a follow up. In the outer most nesting is there a difference between the above two declarations and the following declaration?
foo = function() {...}
It belongs to the current scope, always. For example:
// global scope
// foo is a global function
function foo() {
// bar is local to foo
function bar() {
}
}
Regarding your second question, this:
foo = function() {...}
is an anonymous function expression assigned to a global variable (unless you're running is strict mode, then foo would be undefined). The difference between that and function foo() {} is that the latter is a function declaration (versus a variable declaration, which is assigned an anonymous function expression).
You might be interested in this excellent article about function declarations and function expressions: Named function expressions demystified.
Function declarations are always local to the current scope, like a variable declared with the var keyword.
However, the difference is that if they are declared (instead of assigned to a variable) their definition is hoisted, so they will be usable everywhere in the scope even if the declaration comes in the end of the code. See also var functionName = function() {} vs function functionName() {}.
Noteworthy distinction taking implicit globals into account:
var foo = function() {
// Variables
var myVar1 = 42; // Local variable
myVar2 = 69; // Implicit global (no 'var')
// Functional Expressions
var myFn1 = function() { ... } // Local
myFn2 = function() { ... } // Implicit global
function sayHi() {
// I am a function declaration. Always local.
}
}
Hopefully that clarifies a little. Implicit globals are defined if you forget a var before your assignment. Its a dangerous hazard that applies to variable declarations and functional expressions.
Your first example (var foo = function() {...}) is called an anonymous function. It is dynamically declared at runtime, and doesn't follow the same rules as a normal function, but follows the rules of variables.

JavaScript hoisting variables from unexecuted branch

So i stumbled upon this behavior
var foo = "bar";
(function(){
if(false) {
var foo = "this truns the variable to undefined";
}
console.log(foo); // => undefined
})();
I understand the concept of hoisting. But shouldn't that only happen if the branch is executed?
var foo = "bar";
(function(){
if(false) {
foo = "this scenario is just fine";
}
console.log(foo); // => "bar"
})();
Due to variable hoisting and the fact that locally declared variables hide global variable of the same name, your first block of code is equivalent to this:
var foo = "bar";
(function(){
// define new local variable foo that hides the global one
var foo;
if(false) {
foo = "this truns the variable to undefined";
}
console.log(foo); // => undefined, local foo has not been assigned a value
})();
Because of hoisting, the variable is defined at the start of the function block, regardless of execution path within the function. Variables declared with var are scoped to the entire function and all definitions within the function are hoisted to the top of the function.
Variables defined with let (ES6 feature) are scoped to the block in which they are declared (still hoisted to the top of the block), but their definition is confined to the block in which they are declared, not the function in which they are declared. So, if you used let instead of var, you would get a different result.
Thus, in your first block of code, you are declaring a new variable foo at the start of your function and that new declaration will hide the global definition by the same name such that any reference to foo inside that function will refer to the local one.
The conditional if statement only affects the assignment to foo, not the declaration of foo. Thus, if the if statement does not execute, then foo is undefined since it was never assigned a value.
In your second code block, no new local foo variable is defined so all references to foo are simply referring to the global foo and since no new variable is declared, there is no hoisting. This second code block behaves identially whether the IIFE function is there or not - it's just a simple if statement that decides whether to change the value of the global foo or not.

Ways to break JavaScript Scope

JavaScript normally follows the function scope i.e. variables are accessible only within the function in which they are declared.
One of the ways to break this convention and make the variable accessible outside the function scope is to use the global window object
e.g.
window.myVar = 123;
My question is are there any other ways in JavaScript/jQuery to make the variable accessible outside the function scope?
Not with variable declarations, no. You can obviously declare a variable in an outer scope so that it's accessible to all descendant scopes:
var a; // Available globally
function example() {
a = "hello"; // References a in outer scope
}
If you're not in strict mode you can simply remove the var keyword. This is equivalent to your example:
// a has not been declared in an ancestor scope
function example() {
a = "hello"; // a is now a property of the global object
}
But this is very bad practice. It will throw a reference error if the function runs in strict mode:
function example() {
"use strict";
a = "hello"; // ReferenceError: a is not defined
}
As you wrote, variables are only visible inside the function in which they were defined (unless they are global).
What you can do is assign variables to the function object itself:
function foo() {
foo.myVar = 42;
}
console.log(foo.myVar); // outputs "undefined"
foo();
console.log(foo.myVar); // outputs "42"
But I would advise against it. You should really have a very good reason to do something like this.
You can define them as part of a global object, then add variables later
// Define your global object
var myObj = {};
// Add property (variable) to it
myObj.myVar = 'Hello world';
// Add method to it
myObj.myFunctions = function() {
// Do cool stuff
};
See the link below:
Variable declaration
Also, you can declare it without the var keyword. However, this may not be a good practice as it pollutes the global namespace. (Make sure strict mode is not on).
Edit:
I didn't see the other comments before posting. #JamesAllardice answer is also good.

Behavior of scope in JavaScript [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Confused by Javascript's variable scope
For example, this is my JavaScript code:
var foo = 'Originalvalue';
var foo = 'Nextvalue';
alert(foo); // Nextvalue
So then, now I am sure writing var in front of an already-declared variable just simply is nullified and of no use to the program.
But then consider this program:
var foo = 'Originalvalue';
function duhfoo() {
var foo = 'Newbievalue';
}
duhfoo();
alert(foo); // Originalvalue
Then, from the logic explained in my first example, the value should be 'Originalvalue', as there is already a variable called foo. Then why is it like so?
In Javascript there are two kinds of variables: local variables and global variables.
When using var outside of functions you are declaring a global variable and the same happens if you don't use var at all. Writing
foo = "first";
at top level (outside any function) is the same as var foo = "first".
When inside a function however things are different, and the keyword var discriminates between local and global variables:
var foo = "first";
var bar = "second";
function f()
{
var foo = "third"; // local
bar = "fourth"; // global
}
f();
alert([foo, bar]); // output will be first,fourth
In other words when you use var inside a function the variable will be a different one with the same name, visible only by code written inside the boundaries of the function.
Please note that the boundary is determined by the function, and not the braces {...}. If you have nested blocks and use another var declaration inside the blocks the variable will be the same and this is different from what happens in other languages like Java, C or C++.
The only way to create a scope is to define a function (including a function inside a function).
Another very important thing to remember in Javascript (especially if having been exposed to similar-looking languages in which this concept is not present like Java, C or C++) is the idea of "capture"/"closure"...
var foo = "first";
function f()
{
// Local variable
var foo = "second";
function g()
{
// This is the local foo of f, not the global
// one even if there is no "var" declaration
// inside this nested scope
return foo;
}
return g;
}
var nested_function = f();
alert([foo, nested_function()]); // output will be first,second
Basically a local variable can "outlive" the function that defined it, by being used by other functions that are said to "capture" that variable. A function that captures one or more variable is called "closure".
In other words a local variable is only visible inside the body of the function, but it may live longer than then function like it happens for the local foo of last example in which the variable survived after returning from f because it has been captured by closure g.
well variable foo inside duhfoo clearly states that its scope is duhfoo() method and not global.
Because
(From MDN)
var has the following properties
function-scoped
hoist to the top of its function
redeclarations of the same name in the same scope are no-ops
Please read this for more information on this subject.

Global and Local and Private Functions (Javascript)

I am currently reading a book on Javascript by Pragmatic, and I'm confused about one thing. They have a section on how to make variables global, local, or private.
What is the difference between local and private variables? Is there one?
How does one make a variable global or local, They said something about putting 'var =' before it, but it was very vague.
None, People use "private" because they are mistaken and are meant to say "local"
local variables are defined as
var foo = "local";
global variables are a properties of the global scope object (which is window in the browser)
window.foo = "global";
The fact you can do foo = "global"; without first declaring variable foo with var foo is a "bug". This is fixed in ES5 strict mode.
(function () { "use strict"; foo = 42; })()
gives ReferenceError: foo is not defined
Note that you can make variables global by declaring them in outer most scope
var foo = "global";
function bar() {
var foo = "local";
}
It should be noted that you shouldn't have any code in outer most scope, ever. You should be wrapping all your scope in anonymous functions so that you get "module level scope". This means you have a per file based top level scope. This is part of the module pattern.
In the context of the browser, the var keyword scopes the variable to that of the current function.
var a = 10;
var b = function(a) {
console.log(a); # 15
}
b(15);
console.log(a); # 10
If you do not include the var keyword, it is assigned the scope of window and is considered global. Unless you have a very good reason to exclude it, always include the var keyword.
A variable is considered private if it only exists inside a function scope. This commonly takes the form of an anonymous function. This is not actually a private variable in the common sense of the term, it is simply a local variable.
(function() {
var x = 10;
})();
console.log(x); #undefined
What is the difference between local and private variables? Is there
one?
Depends in which context they are used. Generally they mean the same thing. From the OOP perspective, a local variables is usually called private.
How does one make a variable global or local, They said something
about putting 'var =' before it, but it was very vague.
When you put var before variable, it becomes local variables, in the absence though, it becomes global variable. For example:
var foo = 1; // local
foo = 1; // global equivalent to window.foo = 1 becomes part of window object
More Practical Example:
function myfunc(){
var foo = 1; // presence of var keyword
bar = 2; // absence of var keyword
}
alert(foo); // error eg undefined
alert(bar); // 2 because bar is part of window global object
Javascript has a function scope, any variable defined within a function with a var keyword is local to the function and is not visible outside. variables defined in function without var keyword are globals and are visible everywhere.
function test(){
var local = 'local'; // this is local
global = 'global'; // this is global
}
test(); // call a function
alert(local) // undefined
alert(global) // global
Private variables only make sense when you are constructing objects. The typical prototype pattern has you add any necessary variables and helper functions as properties of the instance of the object and/or its prototype, but this has the disadvantage of making them visible to anyone with access to the object. To avoid this, there is an alternative pattern where the variables are local variables of the constructor, and all the methods are declared in the constructor scope and only the public ones are assigned as actual properties of the object.
I find all your answers very odd as I thought it was as follow :
/* A globally scoped and public variable */
var globalVariable = 'global';
/* A globally scoped and public constructor */
function Obj() {
/* private */
/* A locally scoped and private variable */
var privateVariable = 'private';
/* A locally scoped and private method */
privateMethod = function() {
return privateVariable;
}
/* public */
/* A locally scoped and public variable */
this.publicVariable = 'public';
/* A locally scoped and public method */
this.publicMethod = function() {
console.log(privateVariable + ' ' +
privateMethod() + ' ' +
globalVariable + ' ' +
this.publicVariable);
}
};
/* A globally scoped and public object */
var obj = new Obj();
/* displaying various variables and calling methods */
console.log(globalVariable); // global
console.log(obj.privateVariable); // undefined
/* if uncommented will display : ReferenceError: privateVariable is not defined */
// console.log(privateVariable);
/* if uncommented will display : TypeError: obj.privateMethod is not a function */
// obj.privateMethod();
privateMethod(); // nothing is displayed
console.log(obj.publicVariable); // public
obj.publicMethod(); // private private global public

Categories