confusion of javascript closure - javascript

I have been proved I do not truly understand javascript closure, and I am being confused by the following codes. I thought fxn would access the outside foo, but it actually print out "underfined". Why??
var foo = "hello";
function fxn(){
alert(foo);
var foo = "test"
}
fxn();

This is because in JavaScript, variables get hoisted, which means
Variables are initialised to undefined when created. A variable with
an Initialiser is assigned the value of its AssignmentExpression when
the VariableStatement is executed, not when the variable is created.(ES5 §12.2)
Thus, semantically, your code would be equivalent, to the following...
var foo = "hello";
function fxn(){
var foo; //Variables are initialised to undefined when created
alert(foo);
foo = "test"; //A variable with an *Initialiser* is assigned the value of its *AssignmentExpression* when the *VariableStatement* is **executed**
}
fxn();

You define your variable foo outside your function. If you repeat calls for var, you redefine the variable inside the function and it loses its allocation.
Remove var in the function to access foo into the function fnx.
var foo = "hello";
function fxn(){
alert(foo);
foo = "test";
}
fxn();
Jsfiddle

Related

JS new Function - logging a variable by name dynamically

We are given a code snippet in run time along with a name of a variable used in code. We want to evaluate the given code and log the value of the variable.
Example:
suppose our code is var foo = "Blah"; and the name of the var is foo.
eval('var foo = "Blah"; let varName = "foo"; console.log(this[varName]);');
yields Blah.
yet
new Function('var foo = "Blah"; let varName = "foo"; console.log(this[varName]);')();
yields undefined.
Is there a way to make get this to work with new Function?
With new Function, you're creating a new function. The code that is executed looks something like:
function someFunction() {
var foo = "Blah"; let varName = "foo"; console.log(this); console.log(this[varName]);
}
someFunction();
There, foo is in local scope of the someFunction. It's not global, so variables declared with var inside the function don't get put onto the global object.
In contrast, eval runs on the top level. Your eval code that is executed looks something like:
var foo = "Blah"; let varName = "foo"; console.log(this[varName]);
which is all on the top level, so the foo variable that was declared gets put onto the global object, the this.
Substitute the variable name into the function definition directly, rather than using this.
let varName = 'foo';
new Function(`var ${varName} = "Blah"; console.log(${varName});`)();
Everything here is about Scope. Global Scope and Block Scope.
Global Scope
Variables declared Globally (outside any function) have Global Scope.
var bikeName = "Honda";
// code here can use bikeName
function myFunction() {
// code here can also use bikeName
}
and
var greeter = "hey hi";
function newFunction() {
var hello = "hello"; //Variables declared Locally (inside a function) have Function Scope.
}
console.log(hello); // error: hello is not defined
Here, greeter is globally scoped because it exists outside a function while hello is function scoped. So we cannot access the variable hello outside of a function.
Block Scope
A block is a chunk of code bounded by {}. A block lives in curly braces.
let times = 4;
if (times > 3) {
let hello = "say Hello instead";
console.log(hello);// "say Hello instead"
}
console.log(hello) // hello is not defined
You should read about them. Things will get clear
Hence in your case:
new Function('var foo = "Blah"; let varName = "foo"; console.log(this[varName]);')();
Everything inside function has function scope and will not be available global!

What will the reference be when a variable and function have the same name?

I have a variable named foo and function named foo.
//variable followed by function declaration
var foo="bar";
function foo(){
return "bar";
}
//function declaration followed by variable
function foo(){
return "bar";
}
var foo="bar";
//When I call foo it returns string bar;
//When I enquired foo() it throws error
What's happening here?Why does the variable name override function declaration?
When I call foo it returns string bar;
Function declarations are hoisted to the top of their scope. The function definition are moved above by the compiler. And then the variable is overwriting to string.
Code is equivalent as
function foo() {
return "bar";
}
// Overwriting the value
var foo = "bar"
So, in both the cases, the output will be 'bar'.
Note that function expressions are not hoisted.
For more information on function hoisting, see Javascript function scoping and hoisting
When I enquired foo() it is undefined
foo here is not a function, it's a string. So, foo() will throw an error
Uncaught TypeError: a is not a function(…)
In a clearer and more explicit way of declaring variables, the latter will take account:
var foo = "bar";
var foo = function () {
return "bar";
};
console.log(foo);
output is a function
and the reversal:
var foo = function () {
return "bar";
};
var foo = "bar";
console.log(foo);
has "bar" as output.
In JavaScript, functions are processed upon entering the corresponding scope.
The variables are processed when the interpreter gets to their declaration.
Therefore in your example, the functions are processed first, the name foo is used by the last function and then overwritten by the variables.
Note that if you declare your function like this
var foo = function() {}
it is actually not processed at the beginning and also overwriting the variables declared beforehand.
var foo="bar";
var foo = function(){
return "bar";
};
They are the same. Don't miss to put ; in the end of line.
both cases will return the string "bar"
basically javascript grabs all functions and put them in the top of the file
its called hoisting .
so the string declaration will overwrite the function expression in both cases ;

What is the difference between declaring a function as a variable?

Does this produce the same results? What if function foo does not exist?
var foo = foo || function(){
console.log("I'm Batman");
}
vs
var foo = function() {
console.log("I'm Batman")
}
It's a way of declaring foo if and only if it has not already been declared in some other scope. If it has, then the new, more local foo shall be identical to the broader one.
It works because of what || does and because foo is undefined if it's not, um, defined.
The whole thing is pretty rare, though, and not one of the usual ways to declare a function.
It is known as guard operator ... one feature of javascript
x = a || b;
// if the first is true will return the first. Else will return the second;
Look more about in this question:
Javascript || operator
Hope it helps..
The code does this (more or less):
If foo was not declared in the current scope, it declares it and sets its value to undefined. If it's already declared, it remains declared with the same value.
It checks if the value of foo is truthy.
If it's truthy, the value of foo is not changed
If it's falsy, foo is overwritten with the new value.
Therefore
If foo was not declared in the current scope, it is declared, and the new value is assigned.
var foo = 123; // Another scope
(function() {
var foo = foo || 'abc';
foo; // 'abc'
})();
If foo was declared in the current scope and its value was falsy, foo is overwritten with the new value.
var foo = ''; // Same scope, falsy value
var foo = foo || 'abc';
foo; // 'abc'
If foo was declared in the current scope and its value was truthy, foo is not altered.
var foo = 123; // Same scope, truthy value
var foo = foo || 'abc';
foo; // 123

Scope of variables (Hoisting) in Javascript

One of my friends was taking an online quiz and he asked me this question which I could not answer.
var global = false;
function test() {
global = true;
return false;
function global() {}
}
console.log(global); // says false (As expected)
test();
console.log(global); // says false (Unexpected: should be true)
If we assume that functions are hoisted at the top along with var variables, let's try this one.
var foo = 1;
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
bar();
console.log(foo); //says 1 (But should be 11) Why 1 this time ??
Here is a JSBin Demo and JSBIN Demo2 to play with.
PS: If we remove function global() {} from test(), then it runs fine. Can somebody help me understand why is this happening ?
var statements and function declaration statements are "hoisted" to the top of their enclosing scope.
Therefore, the function global(){} in your function creates a local global name.
Assigning to global inside your functions binds to this local name. Here's how you can "rewrite" it using hoisting to understand how the compiler sees it:
function test() {
var global = function() {}; // hoisted; 'global' now local
global = true;
return false;
}
I'll answer the second part of your question,
If we assume that functions are hoisted at the top along with var variables
bar();
console.log(foo); //says 1 (But should be 11) Why 1 this time ??
You should try console.log(bar()); console.log(foo); instead. However, what hoisting does to your function is this:
function bar() {
var foo;
function foo() {}
return foo;
foo = 10;
foo = 11;
}
So you should expect to get the function returned, since your variable assignments are after the return statement. And both the var and the function declaration make foo a local variable, so the global foo = 1 is never changed.

Declaring variables with this or var?

What is the difference between declaring a variable with this or var ?
var foo = 'bar'
or
this.foo = 'bar'
When do you use this and when var?
edit: is there a simple question i can ask my self when deciding if i want to use var or this
If it is global code (the code is not part of any function), then you are creating a property on the global object with the two snippets, since this in global code points to the global object.
The difference in this case is that when the var statement is used, that property cannot be deleted, for example:
var foo = 'bar';
delete foo; // false
typeof foo; // "string"
this.bar = 'baz';
delete bar; // true
typeof bar; "undefined"
(Note: The above snippet will behave differently in the Firebug console, since it runs code with eval, and the code executed in the Eval Code execution context permits the deletion of identifiers created with var, try it here)
If the code is part of a function you should know that the this keyword has nothing to do with the function scope, is a reserved word that is set implicitly, depending how a function is called, for example:
1 - When a function is called as a method (the function is invoked as member of an object):
obj.method(); // 'this' inside method will refer to obj
2 - A normal function call:
myFunction(); // 'this' inside the function will refer to the Global object
// or
(function () {})();
3 - When the new operator is used:
var obj = new Constructor(); // 'this' will refer to a newly created object.
And you can even set the this value explicitly, using the call and apply methods, for example:
function test () {
alert(this);
}
test.call("hello!"); //alerts hello!
You should know also that JavaScript has function scope only, and variables declared with the var statement will be reachable only within the same function or any inner functions defined below.
Edit: Looking the code you posted to the #David's answer, let me comment:
var test1 = 'test'; // two globals, with the difference I talk
this.test2 = 'test'; // about in the beginning of this answer
//...
function test4(){
var test5 = 'test in function with var'; // <-- test5 is locally scoped!!!
this.test6 = 'test in function with this'; // global property, see below
}
test4(); // <--- test4 will be called with `this` pointing to the global object
// see #2 above, a call to an identifier that is not an property of an
// object causes it
alert(typeof test5); // "undefined" since it's a local variable of `test4`
alert(test6); // "test in function with this"
You can't access the test5 variable outside the function because is locally scoped, and it exists only withing the scope of that function.
Edit: In response to your comment
For declaring variables I encourage you to always use var, it's what is made for.
The concept of the this value, will get useful when you start working with constructor functions, objects and methods.
If you use var, the variable is scoped to the current function.
If you use this, then you are assigning a value to a property on whatever this is (which is either the object the method is being called on or (if the new keyword has been used) the object being created.
You use var when you want to define a simple local variable as you would in a typical function:-
function doAdd(a, b)
{
var c = a + b;
return c;
}
var result = doAdd(a, b);
alert(result);
However this has special meaning when call is used on a function.
function doAdd(a, b)
{
this.c = a + b;
}
var o = new Object();
doAdd.call(o, a, b);
alert(o.c);
You note the first parameter when using call on doAdd is the object created before. Inside that execution of doAdd this will refer to that object. Hence it creates a c property on the object.
Typically though a function is assigned to a property of an object like this:-
function doAdd(a, b)
{
this.c = a + b;
}
var o = new Object();
o.doAdd = doAdd;
Now the function can be execute using the . notation:-
o.doAdd(a, b);
alert(o.c);
Effectively o.doAdd(a, b) is o.doAdd.call(o, a, b)
var foo = 'bar'
This will scope the foo variable to the function wrapping it, or the global scope.
this.foo = 'bar'
This will scope the foo variable to the this object, it exactly like doing this:
window.foo = 'bar';
or
someObj.foo = 'bar';
The second part of your question seems to be what is the this object, and that is something that is determined by what context the function is running in. You can change what this is by using the apply method that all functions have. You can also make the default of the this variable an object other than the global object, by:
someObj.foo = function(){
// 'this' is 'someObj'
};
or
function someObj(x){
this.x=x;
}
someObj.prototype.getX = function(){
return this.x;
}
var myX = (new someObj(1)).getX(); // myX == 1
In a constructor, you can use var to simulate private members and this to simulate public members:
function Obj() {
this.pub = 'public';
var priv = 'private';
}
var o = new Obj();
o.pub; // 'public'
o.priv; // error
Example for this and var explained below:
function Car() {
this.speed = 0;
var speedUp = function() {
var speed = 10; // default
this.speed = this.speed + speed; // see how this and var are used
};
speedUp();
}
var foo = 'bar'; // 'var can be only used inside a function
and
this.foo = 'bar' // 'this' can be used globally inside an object

Categories

Resources