Bit confused between JavaScript Hoisting and Functional Scope - javascript

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

Related

Why I cannot access this variable inside this simple function?

Im new to Javascript and I dont understand whats happening how the scope works in the following codes:
//Code n°1:
let num = 1;
function test(){
console.log(num);
}
test() //As I expected I get in console "1"
//Code n°2:
let num = 1;
function test(){
let num = 2;
console.log(num);
}
test() //As I expected I get in console "2"
But here is the problem:
//Code n°3:
let num = 1;
function test(){
console.log(num)
let num = 2;
console.log(num);
}
test() //I expected to get in console "1" and then "2" but instead I get an error.
When I run in my browser the code n° 3 Im getting this error:
Uncaught ReferenceError: can't access lexical declaration 'num' before initialization
If I look at code 1 and 2 I suppose that after running code 3 I will get in my console the number 1 and then number 2. But that isnt happening. Why?
Thank you so much!
The JavaScript exception "can't access lexical declaration `variable' before initialization" occurs when a lexical variable was accessed before it was initialized. This happens within any block statement, when let or const declarations are accessed before they are defined.
When the 'test function' is called, the function body gets executed. When it reaches to 'console.log(num)', it starts to search for the 'num variable declaration' (or 'num assignment' or 'num reassignment) in the test function scope. So it finds the variable declaration in the next line. The priority for searching for a variable is:
Current Scope
Closure
Scope Chain
So, when the variable declaration is found i the current scope, searching is not continued to scope chain. (It will not search for num variable in global scope.)
I guess this is the reason of the error, but as I am new to javaScript, I am not completely sure.
If you initialize the variable without redeclaring, it will work normally, now if you redeclar the variable, then this error will happen with let or var, because in the same scope, it is being called by the previous console.log().
It is not recommended that you re-declare let variables, if you need to, don't use the same in previous statement, note that if you comment on the first console.log(), the code will work again, this occurs exactly for the lifetime of the variable within this scope, in this case, let
let num = 1;
function test(){
console.log(num)
let num = 2;
console.log(num);
}
test()
Bacause in javascript functions and variables declared with var are hoisted, moved up to the top of the function/lexical block.
But let keyword respect the lexical flow. It pins variable where it is declared.
console.log try to access a variable that is declared bellow in the flow.
So move up manually your let declaration to be above de console.log or change it to var let num = 2; to let javascript engine move it above all automatically.
var num = 1;
function test(){
let num = 2;
console.log(num);
}
test()
or
var num = 1;
function test(){
console.log(num)
var num = 2;
console.log(num);
}
test()
or, to get access to global var num, which is shadowed by declarations from test's body, var or let, no matter
var num = 1;
function test(){
console.log(num)
//let num = 2;
console.log(num);
}
test()

Chrome devtools console does not display closure

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);

JS Global and Local Variables

I have been struggling trying to get some code to work and I think its due to my variable scopes. Instead of posting all my code here, I just made a simplified version to ask "why doesn't this work":
$(document).ready(function() {
console.log("INITIALIZE");
var aGlobalVariable = 25;
function testFunction(){
var aLocalVariable = 5;
var sumVariables = aGlobalVariable + aLocalVariable;
console.log(sumVariables);
}
});
I would expect the testFunction to be able to see aGlobalVariable, add 25 to 5, and output 30. it doesn't do this. I can't even see the global variable if I try to do a console.log of it:
Is a variable declared at the start of a document not a global one????
thanks!
aGlobalVariable is indeed known inside testFunction. Make a call to that function and check out the console:
$(document).ready(function() {
console.log("INITIALIZE");
var aGlobalVariable = 25;
function testFunction() {
var aLocalVariable = 5;
var sumVariables = aGlobalVariable + aLocalVariable;
console.log(sumVariables);
}
testFunction();
});
Here's a jsfiddle showing this:
https://jsfiddle.net/0c8rpLmj/
aGlobalVariable is undefined when you try to view it via the console since it's not in fact global (you have defined it under the ready function scope).
That isn't a global variable. Define it outside of the ready function.
var aGlobalVariable = 25;
$(document).ready(function() {
console.log("INITIALIZE");
function testFunction(){
var aLocalVariable = 5;
var sumVariables = aGlobalVariable + aLocalVariable;
console.log(sumVariables);
}
});
Now you should be able to see it work.
Function expressions create variable scopes too.
$(document).ready(function() {
var aGlobalVariable = 25;
Your variable is inside a function and declared with var so it isn't a global.
Move it outside the function expression if you want to make it a global.
var aGlobalVariable = 25;
$(document).ready(function() {
That said, making it a global probably isn't a good idea. Keeping it inside a local scope, but accessible to all the functions in that scope, means you have less change of other scripts interfering with your variable.

Declaring two variable with the same name

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/

Output of this javascript and the reason

function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
var ctr = getCtr();
ctr();
ctr();
I've been using Javascript from last five years, but this question made me dumb in last interview. I tried everything to my knowledge but can't figure it out.
Can you please help me with the output and reason for it so that I can be better equipped for future interviews if I have one.
var ctr = getCtr();
This calls getCtr(), which initializes i to 0, and stores a reference to the function
function() {
console.log(++i)
}
in ctr. Because that function was created in the scope of getCtr(), the variable i is still accessible in the scope of the function stored in ctr.
The first call to
ctr()
executes console.log(++i) which has a preincrement on i, so it prints out 1. The second call executes the same code, with the same preincrement, and prints out 2.
DISCLAIMER: Not a javascript developer. Forgive me if I've made an error or used some unpreferred wording.
So the code you posted outputs 1 2. Yet the code:
function getCtr(){
var i = 0;
return function(){
console.log(++i);
}
}
getCtr()();
getCtr()();
outputs only 1 1!
The difference is that if you save a reference to getCtr() by using the var ctr = getCtr();, you create what is called a closure.
So the difference between calling getCtr()() and ctr() is that ctr has i defined in its scope, and that scope is saved thanks to var ctr = getCtr();. Because the reference is saved, the function inside of ctr is able to always act on the same variable.
run this:
var m=0;
var d=0;
alert(m++ +":"+ ++d);
and you get "0:1"
IF it were me asking in an interview, the difference in where the ++ is is what I would be after :)
http://jsfiddle.net/MarkSchultheiss/S5nJk/
Closures
The return statement in that function saves i. So when var i = 0; is only called var ctr = getCtr();. Then ctr becomes the returned function:
function () {
console.log(++i)
}
and the variable ctr has i in the scope of the outer function, getCtr() and the return function is in the scope of getCtr() as well.
okay, getCtr is a function that returns an other function.
It also contains a var called "i" which is set to 0.
"i" is also available in the scope of the returned function.
the preincrement of "i" before logging it to the console causes that it increases by 1 every time the returned function, which is stored in "ctr", is called.
When executed, function getCtr returns an inner anonymous function.
This function is now referenced by variable ctr
Because the anonymous function was created inside getCtr it will have access to getCtr private scope object, which contains variable 'i'. This is known as a closure.
var ctr = getCtr()
Every time the anonymous function is executed it pre-increments i, and writes in in the console.
ctr()
Lets break it down using terms you might know from classical inheritance based OOP languages:
// In javascript functions are first-class objects
// This function is being used like a class would be in Java
function getCtr(){
// You can think of this as a private variable of the getCtr "class"
var i = 0;
// Because it is returned, this is effectively a public method of getCtr
return function(){
// Which increments i and then prints it.
console.log(++i);
}
}
// This makes the variable ctrl an instance of getCtr.
var ctr = getCtr();
// This calls ctr's only public method.
ctr();
ctr();
So the output would be "1, 2".
What this question is meant to do is test if you understand Javascript's prototypal inheritance, ability to have anonymous functions, and closures.
A clarified version of that could that would do the same thing would be:
var myProtoype = function() {
var privateVariable = 0;
var privateMethod = function () {
privateVariable++;
console.log(privateVariable);
}
return {
publicMethod: privateMethod
};
}
var myInstance = new myPrototype();
myInstance.publicMethod();
myInstance.publicMethod();
That function is a Javascript Module. You can have a good reading about it on Javascript: the Good Parts, which is a great book and I highly recommend. A Module uses Javascript closures to create private variables and if assigned to a var the var will retain it's vars each time it's called instead of redefining the vars.
A module works like this
function moduleName(privateVar1){
var privateVar1;
var privateVar2;
return {
exposedFunction1: function (var1) {
// Do stuff... using private vars
return something;
},
exposedFunction2: function (var1, var2) {
// Do stuff...
return something;
}
}
}
var moduleInstance = moduleName(privateVar1);
moduleInstance.exposedFunction(var1);

Categories