Behavior of scope in JavaScript [duplicate] - javascript

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.

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.

What's the difference of passing an parameter to the left-hand side as opposed to the right hand-side?

Why is it that when I do the following:
var a = 1;
function foo(a) {
a = 2;
}
foo();
console.log(a); // a = 1
But I get a different result for the following:
var a = 1;
function foo() {
a = 2;
}
foo();
console.log(a); // a = 2
In the first example the function foo parameter a is shadowing the global variable a and thus the value of the global variable never changes. The code in the first example is equivalent to this one:
var a = 1;
function foo(x) {
x = 2;
}
In the second example you are referencing the global variable a inside the body of the function foo. Here no variable shadowing occurs so that you get the expected result - a is asigned the value of 2.
JavaScript doesn't really have "parameters on the left/right side." Your first example passes a parameter. Your second example uses a closure.
In programming languages, closures (also lexical closures or function closures) are techniques for implementing lexically scoped name binding in languages with first-class functions. Operationally, a closure is a record storing a function together with an environment: a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created. A closure—unlike a plain function—allows the function to access those captured variables through the closure's copies of their values or references, even when the function is invoked outside their scope.
In your first example, the variable a inside the function foo is a different variable than a outside of the function. Changing foo's parameter a has no effect on the global variable a that gets passed to console.log.
In your second example, the variable a is not a parameter, but rather a part of the environment that is captured by the function foo. The log shows a modified value of a because the assignment inside foo and the console.log call outside of foo are actually referring to the same variable.
if a is passed in as an argument to that function -- then the value of a within that function is isolated and only accessible within that function. otherwise your a defined outside the function is shared across all functions and objects.
agree with #RomanPerekhrest -- read up.
**UPDATE in reply to comment **
var a = 1;
function foo(a) {
a = 2;
}
foo();
console.log(a); // a = 1
In the code above, the reference to a on lines 2 and 3 are a different variable from the a on lines 1 and 6. In the code from your comment, you are setting a to the value of x within the foo function. That's a bit different from the original question. No?

Javascript: Global variable used before local variable is used (example from jQuery JavaScript tutorial)

In the jQuery tutorial on JavaScript (http://learn.jquery.com/javascript-101/scope/) there is the following example on scope:
var myFunction = function() {
var foo = "hello";
var myFn = function() {
console.log( foo );
};
foo = "world"; // line x
return myFn;
};
var f = myFunction();
f(); // "world"
Now I'm wondering why the output is world instead of hello. The variable foo is locally bound inside myFunction. Then in myFn, foo is accessed. I would say the evaluation should go down the scopes, which would be declaration inside myFn, then declaration inside myFunction and the last one should be the global variable.
So why is the global variable output even though the definition inside myFunction is less far away in the scope?
If I remove the line marked with line x, the local variable is output as expected.
foo is a local variable in the myFunction context. So when you call the myFn function you're accessing the actual (last in this case) value of the foo variable.
Note that there's an error in the question title. foo is not global. But local to myFunction
Functions are Objects in Javascript and Objects are passed by reference not value. Also, returning an Object is in essence passing the Object. Or, you could refer to it as returning by reference.
The myFn function being run in the global space retains the same scope it was defined in. This is what causes f() to adhere to changes made to the foo variable and to access the foo variable to begin with.
The layout of text is slightly misleading here http://learn.jquery.com/javascript-101/scope/. Text referring to code further down the page is followed by a colon. The text you are referring to is for the code above it, which is most likely what was causing confusion.

Can I explicitly reference a JavaScript global variable that's been shadowed by a local with the same name?

I've seen tons of posts about the difference between global and function scope in JavaScript, far too many to link here. I've also seen my exact question asked about Python. So what I want to know is, how can I access a global variable when a "closer" scope also has a variable with the same name?
var a = "global";
function b(){
var a = "local";
var magic = ...; // somehow put "global" in magic
console.log(magic); // should print "global"
}
In browser only, I figured out that you can use window.a to specify the global. Is there anything that works server-side as well?
If it's really a global (i.e. not just in the outer scope), you can do this :
var magic = (function(name){return this[name]}).call(null, "a");
From ECMAScript's documentation (10.4.3) :
Entering Function Code
The following steps are performed when control enters the execution
context for function code contained in function object F, a caller
provided thisArg, and a caller provided argumentsList:
If the function code is strict code, set the ThisBinding to thisArg.
Else if thisArg is null or undefined, set the ThisBinding to the
global object.
Note that you can't test this in jsFiddle, as the global scope isn't where you define your a.
Demonstration:
var a = "global";
function b(){
var a = "local";
var magic = (function(name){return this[name]}).call(null, "a");
document.body.textContent = 'a: '+JSON.stringify(magic); // print "global"
}
b();
There is no standard to do that. For my own purposes, I always put my variables in a container where the name resembles the project name:
var PROJECT = {}; // Put all "globals" for "project" into this container
That way, I can collect all variables in one place and if I need to pass the "globals" around, I have to pass at most one reference.
Using your code as the basis of the answer, you could use the following to actually pull the global version of "a" as opposed to the local version:
var a = "global";
function b(){
var a = "local";
var magic = this.a; // somehow put "global" in magic
console.log(magic); // should print "global"
}
b();
This will only work if you are calling the b() function in the form above. An example in which this will not work is as follows:
var a = "global";
function b(){
var a = "local";
var magic = this.a; // somehow put "global" in magic
console.log(magic); // should print "global"
}
b.call({a : "other context"});
In the case above, "other context" will be printed to the console.
You can access the global through the global object. In this case window and the local by name inside the current context.
Here is an fiddle example.
well I don´t have a direct answer, but a workaround is to use a well established container, window for example
window['a'] = "global";
This isn't a very clean solution but it does the job

what's the difference between var function and function in javascript? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
JavaScript: var functionName = function() {} vs function functionName() {}
Function declaration - Function Expression - Scope
I've learned about var a = 1, is defining a local variable, but talk about function, I thought It's only available within the current scope as the var variable behave, what's the difference between the following two code snippet?
function aPrint() {
console.log('a');
}
var a = function aPrent() {
console.log('a');
}
Your first example is a "function declaration". It declares a function that will be available anywhere in the scope in which it is declared (so you can call it before it appears in the source code). This is sometimes known as "hoisting" (as in, it gets hoisted to the top of its scope).
Your second example is a "named function expression". The variable declaration is hoisted to the top of the scope in which it is defined (like a function declaration) but the assignment still happens where you expect it to, so you can't call the function until after it has been assigned to the variable.
There is a third option, which is just a "function expression", where the function does not have a name (it's an anonymous function):
var a = function() {
console.log('a');
}
You will probably find that you have little use for named function expressions (although it can be useful when debugging), so it's usually better to use the anonymous function. In a named function expression, the name is only in scope inside the function itself, so you can't refer to the function by name normally.
here is a best article that may help you.
refer http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
function aPrint() {}
Declares a function (but does not execute it).
It will usually have some code between the curly brackets.
var a = aPrint()
Declares a variable, invokes a function (aPrint) and sets the value of aPrint to the return of the function.
var a= new aPrint()
Creates a new instance of an object based on the aPrint function. So the variable is now an Object, not just a string or a number.
Objects can contain indexed strings, numbers and even functions, and you can add more stuff to them, they're pretty awesome. The whole concept of Object Oriented Programming (OOP) is based on this.

Categories