I was trying out a very basic example of Javascript closure, but I am not able to visualize it in Chrome devtools. Please see the screenshot.
I have created a global variable
var p = 3;
and a function
function f1() {
var q = 2;
return p+q;
}
This function is using the global variable p inside it, so this is a closure, right? Please guide me if my understanding is not correct.
So, if this is a closure then why doesn't it shown in the function scope as "Closure"?
w3schools.com says "A closure is a function having access to the parent scope, even after the parent function has closed." In your example, p is defined in the global scope, not a parent function. If you wrap your code in a parent function, in the dev tools, you will see p listed under closure.
var f2 = function(){
var p = 3;
var f1 = function(){
var q = 2;
return p + q;
}
return f1;
}();
console.dir(f2);
Related
Any function within function forms a closure. Do closures always needs to be in an immediately invoked function?
The first example is where a closure is formed within an iife and works as expected, gives "8" and "7" as output.
var cat = (function (){
var lives = 9;
return function() {
return --lives;
}
}());
console.log("iife");
console.log(cat());
console.log(cat());
In the below example the closure does not work as expected, prints the same value every time.
var cat = function (){
var lives = 9;
return function() {
return --lives;
}
};
console.log("no iife");
console.log(cat()());
console.log(cat()());
A closure is just the link between a function and the scope in which it was created, link which exists when the function uses a variable from this scope.
You have this problem because you don't keep the closure: you're recreating it at every console.log when you call cat().
Change
console.log(cat()());
console.log(cat()());
into
let c = cat();
console.log(c());
console.log(c());
If I'm not wrong var lives is functional scope, because it's inside in function sandeep(). But if I'm doing console.log(lives) outside above the function then still I am getting console result as - New Delhi why? Can any one help me. (Is it because of Hoisting? it's moved on top...)
Screen shot without var define inside function
Screen shot with var inside function
Screen shot- write console.log after function call now it's giving undefined
I got my answer - It was my mistake, my chrome browser didn't refreshed properly. Thanks for every one for their answers.
console.log("Lives become global variable " + lives);
function sandeep() {
lives = "New Delhi";
return lives;
}
sandeep();
You are right about the fact that
var lives is functional scope
But you haven't declare the variable in the function. You need to use var lives = "New Delhi" so that its scope is only in the function in which it is declared.
If you directly assign lives = "New Delhi", it is assigned to global window object. Open browser console and try this.
a = 1
and then
window.a
You'll find that window.a is 1.
Let me know if it helps.
If I'm not wrong var lives is functional scope
This is right but you forgot the var in front of lives. If you define it as a variable you will get an error:
console.log("Lives become global variable " + lives);
function sandeep() {
var lives = "New Delhi";
return lives;
}
sandeep();
Only var are working as global & functional scope.
Global scope
var x=5;
function callvar(){
console.log(x);//5
var x=3;
console.log(x);//3
}
colsole.log(x);//3
function scope:
function one(){ var x = 5;
console.log(x)//5
}
console.log(x)// reference error
function two(){ var x = 4;
console.log(x)//4
}
console.log(x)// reference error
let & const are in block scope
functional scope is one type of block scope
if(true){
let x = 5;
console.log(x);//5
}
console.log(x) // reference error
function emergency() {
var ambulance = 100;
var callAmbulance = function() { alert(ambulance); }
ambulance++;
return callAmbulance;
}
var accident = emergency();
accident(); // alerts 101
I am referring to the variable 'ambulance'.
When I call accident(); it should call emergency() which should use the declared variable 'ambulance' [considering the global scope thing in javascript, still it could set the value to global] but its using old value 101 instead of setting again back to 100 - behaving more like static var.
What's the Explanation?
What you have there is called a closure. It means a function can access variables declared in outer functions (or in the global scope). It retains access even after the 'parent' function has returned. What you need to understand is that you don't get a copy. The changes performed on that variable are visible to your inner function, which in theory means you could have multiple functions sharing access to the same variable.
function f () {
var x = 0;
function a() { x += 1; }
function b() { x += 2; }
function show() { console.log(x); }
return {a:a, b:b, show:show};
}
var funcs = f();
funcs.a();
funcs.b();
funcs.show(); // 3
One thing to be aware of is that a subsequent call to f will create a new scope. This means a new x variable will be created (new a, b, show functions will be created as well).
var newFuncs = f();
newFuncs.a();
newFuncs.show(); // 1
funcs.a();
funcs.show(); // 4
So, how do you get a copy? Create a new scope.
function g () {
var x = 0;
var a;
(function (myLocal) {
a = function () { myLocal += 1; }
}(x));
x += 200;
return a;
}
JS only has pass-by-value so when you call the anonymous function, the xvariable's value will be copied into the myLocal parameter. Since a will always use the myLocal variable, not x, you can be certain that changes performed on the x variable will not affect your a function.
If, by any chance, you're coming from a PHP background you are probably used to do something like
use (&$message)
to allow modifications to be reflected in your function. In JS, this is happening by default.
You are creating a function definition which is not compiled at this time:
var callAmbulance = function() { alert(ambulance); }
And before you are sending it to the called function, you are incrementing the num:
ambulance++;
And then you are sending it to the called function:
return callAmbulance;
But whether you are sending it there or not, it doesn't matter. The below statement executes or compiles the function:
var accident = emergency();
And this takes in the current ambulance value which is 101 after the increment. This is an expected behaviour in creating function but not executing it. Please let me know, if you didn't understand this behaviour. I will explain it more clearly.
Is it possible to call the same name variables which set outside of the function?
var a = $(window).width(); // I want to call this variable
if(!$.isFunction(p)){
var a = $(window).height(); // Not this one
alert(a);
}
FIDDLE
In this case, you have actually redefined the value of a. There is absolutely no way of referencing a different variable with the same name, as it just acts as a redefinition.
If you want to declare a global variable you can do so by
window.varname="This is a global variable";
And you can access the same by
alert(window.varname);
Now you can also have a local variable inside a function with the same name
var varname="This is a local variable";
And you can access it normally.
Here's your code so that you can access the global variable not the local one.
var p = ['foo',''];
window.a = $(window).width();
if(!$.isFunction(p)){
var a = $(window).height();
alert(window.a);
}
In a code snippet such as yours, the variable a is being redefined. This is because an if statement doesn't create another scope for variables. However, functions do.
In a case like this:
var a = 0; // global
function doStuff() {
var a = 10; // local
alert(a);
alert(window.a)
}
alert(a);
doStuff();
alert(a);
inside the function doStuff, the variable a is being redefined. This snipped will therefore alert the numbers 0, 10, 0, 0. This proves that the global variable is not redefined inside the function, as printing a after calling doStuff doesn't change the value of a in the global scope.
The variable a outside of the function can be accessed, as any variable not declared in a non-global scope is placed inside the window object. However, if using this snippet (which calls an anonymous function, creating a new scope):
var a = 0; // global
function doStuff() {
var a = 10; // local
alert(a);
alert(window.a)
function() {
var a = 20; // even more local
alert(a);
alert(window.a);
}();
}
alert(a);
doStuff();
alert(a);
you cannot access the value of a inside the doStuff function. You can still access the global variable using window.a.
In your case, however, the if statement does not create a new scope, therefore you are redefining the variable a to the new value $(window).height().
Example:
var a=10;
if(true){
var a=5;
}
alert(a)// it will return a=5;
var a=10;
var a=5;
//both are same way assign value
In js if statement is not scope it visible every where with in function . you have to change the variable name
There is no blockscope in JavaScript (at least up until ES6).
Like you seem to expect from the if block. See
What is the scope of variables in JavaScript?
for an excellent summary of scopes that do exist in JavaScript.
Beware of Hoisting
Furthermore, you shouldn't sprinkle your var declarations through your code, but explicitly put them in the top of your function. That is where Javscript will hoist them anyway:
# so if you have a function like this
var i = 5;
function testvar () {
alert(i);
var i=3;
}
testvar();
# the alert window will contain undefined.
# because internally, it's been changed into this:
var i = 5;
function testvar () {
var i;
alert(i);
i=3;
}
testvar();
Minimize use of the global scope
Read
What is meant by “leaking” into global scope?
And listen to what Doug Crockford has to say about it. Actually, take an hour and watch the whole talk.
You can do it like this:
var p = ['foo',''];
var a = $(window).width(); // I want to call this variable
if(!$.isFunction(p)){
(function(b){
var a = $(window).height();
alert(b);
})(a);
}
No need to use the global scope, just create an anonymous function and call it with a as the argument. Inside the function b is a reference to the a variable outside the function.
It is a good practice not to modify the window object in javascript to write clean and maintainable code.
Less bugs and problems. I mean, never do the window.a thing. Is evil for your code.
No, you can't because of you have redefined the variable name in the same scope and beacuse of the hoisted variables your code will be interpreted by javascript in the following mode:
var p, a;
p = ['foo',''];
a = $(window).width(); // I want to call this variable
if(!$.isFunction(p)){
a = $(window).height(); // Not this one
alert(a);
}
Now you can easly see that the variable a will be replaced and not created
JavaScript has two scopes: global and local. In your example a is in the global scope both times so you are just redefining it.
However you can specify skip a variable in local scope and get the one from global. Consider this example:
var a = 1;
function foo () {
var a = 2;
console.log("var a is: " + window.a);
console.log("local var a is: " + a);
}
foo ();
Will log "var a is: 1"\n"local var a is: 2\n" to the console. This is about as close as it gets to what you need
var abc = new Array();
abc[0] = 'str1';
abc[1] = 'str2';
Use array in this case
Try this (pattern)
var p = ['foo', ''];
var a = function (name) {
return (
name === "height"
? $(window).height()
: (name === "width" ? $(window).width() : name)
)
};
if (!$.isFunction(p)) {
// `$(window).width()` , `$(window).height()`
alert( a("width") + "\n" + a("height") );
}
jsfiddle http://jsfiddle.net/guest271314/2tuK4/
Is there a way to print the value of temp (a closure variable) from a function defined outside the closure but referenced within the closure without passing temp as a variable to funcA?
var funcA, funcB;
funcA = function () {
console.log(temp);
}
funcB = function () {var temp, funcC;
temp = 1;
funcC = funcA;
funcC();
}
funcB(); // temp is undefined.
This works, but only because funcA is defined within funcB:
funcB = function () {var temp, funcA, funcC;
temp = 1;
funcA = function () {
console.log(temp);
}
funcC = funcA;
funcC();
}
funcB(); // 1
I'm trying to find a way to pull some function definitions out of outer functions to streamline code that's getting a little complex. Can I define funcA outside of funcB but still reference the temp variable without having to pass parameters?
I read that javascript does not have dynamic run time scoping, that it's only lexical scoping, but with referencing a function (funcA via funcC) within funcB, is there a way to meet the lexical scope requirement and provide access to the scoped variables for funcB?
Using Akinkunle Allen's comment, I came up with this which seems to solve my problem.
function funcB () {
var funcA, funcB, temp;
funcA = function () {
console.log(temp);
}
funcB = function () {var funcC;
temp = 1;
funcC = funcA;
funcC();
}
return funcB();
}
funcB(); // 1
Yes, and No.
The keyword var for declaring variables behaves different depending upon what the current scope is. When var is executed on the global scope it is optional. The variable becomes a property of the global object. When executing in the browser this global object is window.
So the following in global space has the same result.
var temp = 1;
window.temp = 1;
this.temp = 1;
All the above is just window.temp because of the global context.
When you use var inside a function then the variable is attached to the function. All functions in Javascript are objects so local var variables will live as long as the parent function is still being used somewhere.
Javascript will walk the hierarchy of executing scopes to find a variable identifier. So any inner functions can access their outer function variables (as in your example).
What you can do is play around with the this reference in functions.
The identifier this in Javascript is dynamic (meaning that you can change it). I can pass a variable to an unknown function that was declared outside the calling function. Since the this.temp is used to reference the variable the function funcA is able to display the value.
funcB = function(otherFunc)
{
this.temp = 1;
otherFunc();
}
funcA = function()
{
alert(this.temp);
}
funcB(funcA);
http://jsfiddle.net/thinkingmedia/dfLvj/
See the above jsfiddle example.
What you can do with this is change the meaning of this on the fly. Here is a better example.
funcB = function(otherFunc)
{
var temp = {
message: "Hello World!"
};
var foo = otherFunc.bind(temp);
foo();
}
funcA = function()
{
alert(this.message);
}
funcB(funcA);
http://jsfiddle.net/thinkingmedia/K5Pw6/
Dynamically changing this can have a lot of benefits by allowing a function to accept closure references that will be executed with a custom this reference.
An example might be a click event handler where this is the DOM element that triggered the event.