Function declarations precedence/overwriting variable declarations? Hoisting? Why? - javascript

Snippet 1:
var a; // undefined variable named 'a'
function a(foo) { // a function named 'a'
var foo = "Hello World";
console.log(foo);
}
console.log(a); // output is: [Function: a], but why not undefined?
Snippet 2:
function a(foo) { // a function named 'a'
var foo = "Hello World";
console.log(foo);
}
var a; // undefined variable named 'a'
console.log(a); // output is: [Function: a], but why not undefined?
I could have just shown Snippet 1 to ask this question - however I showed both just for completeness purposes. I have wrote some brief comments in them as well.
My question is, in both cases, why is the function declaration ‘overwriting’/’shadowing’ or taking ‘precedence’ over the variable declaration? Can someone please explain this behaviour?
I understand that these arguably are the same (from the perspective of the interpreter) in terms of end-result, due to the ‘hoisting’ phenomenon, but why does the function declaration or the variable declaration have precedence over the other when it’s interpreted/parsed by the Javascript engine (during the creation phase)? i.e. which one gets hoisted above the other? I have read it is that the function declaration has precedence over the variable declaration - but why is this the case?
Also, kindly refer to the first code snippet (but this applies to both cases), is the memory location/address of ‘a’ where it’s declared in line 1, and line 6, EXACTLY the same? And since ‘a’, in both places of the code, represents the function declaration, what would be the value of ‘a’ at its memory location/address after parsing line 1 and line 6 during the creation phase? Since function declarations are 'hoisted' above the variable declaration, does that mean that by line 1, 'a's memory address is pointing to the function object 'a', by the end of the creation phase of the execution context?
In both code snippets, ‘var a’ is undefined, so why isn’t ‘a’ the value of undefined by the time we reach the execution phase (which has its execution point starting on line 6?) Does the Javascript engine simply say, “Ah, if we allow ‘var a’ to ‘overwrite’ ‘function a() {…}’, it would continue to be undefined and thus be unusable. Whereas, if we allow ‘a’ to represent said function, then at least the user can invoke said function (even prior to its declaration, without getting a reference error)". This is very unlikely to be the case but sounds logical/ideal, maybe?
So, my questions are:
What’s the reason behind why the function declaration is overwriting or having precedence over the variable declaration? Is it something we just accept prima-facie because it's an implementation of the ECMAScript specifications or can we explain this behaviour?
And
If possible, could someone please answer what is happening in memory when this occurs every step of the way?
I have been trying to use my intuition for the last 8 hours (where I ended up spiraling into another dimension of the other peculiarities of JavaScript, but that’s another issue in itself) but I would to know if there is a simple or concrete explanation or answer to this behaviour.
Any help in understanding all of this would be much appreciated.

My question is, in both cases, why is the function declaration ‘overwriting’/’shadowing’ or taking ‘precedence’ over the variable declaration? Can someone please explain this behaviour?
There is only one place in either snippet where the variable a is given a value, and that's the function declaration. The statement var a; means "I announce that a variable named a exists". Since the function declaration is taking care of announcing that it exists and giving it a value, the var a; statement doesn't really have any effect.
In fact, if we refer to Section 10.5.8 of the JavaScript spec, we can see that the end result of this var a; is literally to do nothing because the a variable is already declared by the time the var a; declaration is processed.
I understand that these arguably are the same (from the perspective of the interpreter) in terms of end-result, due to the ‘hoisting’ phenomenon, but why does the function declaration or the variable declaration have precedence over the other when it’s interpreted/parsed by the Javascript engine during the creation phase?
Nothing is taking "precedence" here. There is only one variable named a. var a; does not give a a value, so it has no effect on a's value.
Also, kindly refer to the first code snippet (but this applies to both cases), is the memory location/address of ‘a’ where it’s declared in line 1, and line 6, EXACTLY the same?
There is only one a variable and it only takes on one value, so this question is mostly nonsensical, but in rough terms, the a variable itself would only exist in one place and it would only refer to one value (memory location), which would be the definition of that function.
Since function declarations are 'hoisted' above the variable declaration, does that mean that by line 1, 'a's memory address is pointing to the function object 'a', by the end of the creation phase of the execution context?
My knowledge of the creation phase isn't that great, but in the course of this code's execution, a only ever refers to one value, as I said above.
In both code snippets, ‘var a’ is undefined, so why isn’t ‘a’ the value of undefined by the time we reach the execution phase (which has its execution point starting on line 6?)
See my first and second answers.
What’s the reason behind why the function declaration is overwriting or having precedence over the variable declaration? And
As I've said, it's not taking "precedence", but the reason JavaScript has function hoisting is in order to allow people to call functions from a line in the code before the function's actual definition, similar to how other major languages like C# and Java do.
If possible, could someone please answer what is happening in memory when this occurs every step of the way?
The JavaScript spec doesn't define what happens in memory. It defines the code's external behavior. So this would be an implementation detail and would be engine-specific.
Here is a rough blow by blow of what happens when your code is executed (in both cases):
Create a variable called a and assign it the value of that function you have there.
Check whether there is a variable called a. There already is one, so do nothing.
Execute console.log and pass it the value of a (which is that function)

The function declaration gets hoisted before the variable hoisting.
console.log(a);
var a = 42; // assignment
console.log(a);
function a(foo) { // a function named 'a'
var foo = "Hello World";
console.log(foo);
}
console.log(a);

Related

Callback definition closure issue

I run into a bit of confusion regarding scoping with respect to where a callback is defined.
function test(){
var b = 3
var fun = function(){
var printingFunction = function(){
console.log(b)
}
printingFunction()
}
return fun
}
test()() //prints 3, as expected because of closures
However, the following doesnt work
function test(){
var b = 3
var fun = function(cb){
cb()
}
return fun
}
test()(function(){console.log(b)}) //b is not defined
I would expect that since the function is passed as an argument and has not been defined before, its definition takes place inside 'fun' and therefore it would have access to b. Instead, it looks a lot like the function is first defined in the scope where its passed and THEN passed as an argument. Any ideas/pointers?
EDIT: Some extra pointers.
someFunction("a")
We couldn't possibly claim that "a" is a definition. What happens here implicitly is that "a" is assigned to a variable named by the argument name so var argumentNameInDefintion = "a". This happens in the body of someFunction.
Similarly we cant claim {} is a definition in : someFunction({}). So why would:
someFunction(function(){})
decide that function(){} is a definition is beyond me. Had it been
var a = function(){}
someFunction(a)
everything would make perfect sense. Maybe its just how the language works.
Scoping in JavaScript is lexical. If you look at your examples, you can see that where printingFunction is defined, lexically (e.g., in the source text) b is declared in a containing scope. But in your second example, it isn't. That's why b can't be resolved in your second example but can in your first.
The way it works is that when a function is created, it has a reference to a conceptual object containing the variables and such in the scope in which it's created (which has a fancy name: "Lexical Environment object"); and that object has a reference to the one that contains it. When looking up a variable reference, the JavaScript engine looks at the current lexical environment object and, if it finds the variable, uses it; otherwise, it looks to the previous one in the chain, and so on up to the global one.
More details can be found:
In this SO question's answers
In this post on my anemic little blog
The issue stems from me not understanding that function(){} on its own is a definition and so is "a" and {}. Since these are definitions then the definition scope of the function passed is appropriately placed where it is and the world makes sense again.
In first case, it is forming a closure and has access to the variable "b" but in second case it does not form a closure at all. If you put a debugger just before the cb() inside the function, you will notice that there is no closure formed and the reason of that being the callback function is suplied to the function as an argument and it becomes local to that function which does not have any knowledge of the variable b.
Think of it as two different functions, one in which it has a local variable "b" and in other no local variable but we are trying to access it which throws the reference error.

Variables with the same name, but the local scope variable isn't being used, why?

Why is the declaration of the variable 'a' not used in the output of the console log of the below code? Doesn't that go against the scope chain? The variable 'a' with the undefined value on line 4 surely should be used on the console output on line 5?
var a = 15;
function checkScope(a) {
var a;
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
I want to understand this behaviour. To confirm, this behaviour has nothing to do with hoisting or even scope (i.e. scope chain)?
I don't believe scope is relevant to explain this behaviour because 'a' exists locally (its value is 'undefined' as it's not initialised) within the function, hence the Javascript engine will not look to the outer lexical environment to find 'a' (which has a value of 15). Or as per the MDN page: "The scope of a variable declared with var is its current execution context", which in this case is the enclosing function 'a'.
I also don't believe this behaviour is a result of hoisting as far as I know.
So, in addition, this is what is stated on the MDN page? "If you re-declare a JavaScript variable, it will not lose its value."?
Off-topic question but, what's the reason behind MDN's statement above? Is it simply related to memory management? There's no point to logical reason to allocate a new memory address every single time a variable is declared?
Now, going back to my question:
Since they're re-declared, If I'm interpreting MDN correctly, does that mean line 3 is basically ignored? But I don't think so because both variable are declared in their own, separate execution contexts, so surely the variable 'a' in line 4 is being used/accessed? Because the scope chain would suggest that the closest local variable would be used (i.e. the local 'a' with a value of undefined), and in addition, I would best think that the MDN statement applies to only re-declared variables only within the same lexical environment, correct?
I am just trying to work out whether 'a' in line 4 is actually used when we refer to 'a' in line 5? Or is line 3 ignored, and thus line 5 will instead access (refer to) the 'a' in line 3 (i.e. checkScope's 'a' parameter)?
- The latter sort of implies the former
It makes sense if line 3 from the above code is simply ignored, because deleting it achieves the same result:
var a = 15;
function checkScope(a) {
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
Thanks.
You have declared a variable named a three times.
Once as a global on line 1: var a = 15;
Twice inside the function:
Once with a var statement on line 4: var a;
Once with an argument definition on line 3: function checkScope(a) {
The line 4 var has no effect. The variable is already declared.
Then you call checkScope(a); which passes the value of the global a (15) to the local a argument of checkScope. This is why it is 15 and not undefined.
Since they're re-declared, If I'm interpreting MDN correctly, does that mean line 3 is basically ignored?
var a is basically ignored.
But I don't think so because both variable are declared in their own, separate execution contexts
This is where you are being tripped up by having three and not two declarations of a. It declares the variable defined by the function argument name.
If you redeclare a JavaScript variable, it will not lose its value.
take a look at this answer.
var a = 15;
function checkScope(a) {
var a; // this is equivalent to redeclaring the variable
console.log(a); // log outputs 15 and not undefined
}
checkScope(a);
Basically line 4
var a;
is where the compiler finds a redeclared variable of the function parameter. Because of the missing initializing, a keeps the value of the handed over value of the parameter a.
Consider 'a' to be different assigned variable for arguments in function and inside as a local variable.
function a != var a;
Now, some 'a' is called by console.log(a). Now, it will search for the default 'a' value if existing, i.e, 'a' of function. Even on manipulation of 'a',
function hoist(a) {
var a;
a*=2;
console.log(a);
}
hoist(10);
output: 20

Value of variable is always undefined [duplicate]

alert(myVar1);
return false;
var myVar1;
Above code throws error in IE, FF and Opera stating that return statement has to come in the function. But it works (shows undefined) in Safari and Chrome.
The above code has been written in global scope. Outside all the functions.
Any reason?
In JavaScript variables are moved to the top of script and then run. So when you run it will do
var myVar1;
alert(myVar1);
return false;
This is because JavaScript doesn't really have a true sense of lexical scoping. This is why it's considered best practice to have all your variables declared at the top of the area they will be used to prevent hoisting causing a problem. JSLint will moan about this.
This is a good article that explains it: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
The return is invalid. If you want to do a true hoisting example (taken from the link above) do
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
This will alert 10
Below is my understanding and I have read it somewhere but can't find all the sources that I read so am open to correction.
This Alerts thanks to the differences in the JavaScript JIT. TraceMonkey(http://ejohn.org/blog/tracemonkey/) I believe will take the JavaScript and do a quick static analysis and then do JIT and then try to run it. If that fails then obviously nothing works.
V8 doesn't do the static analysis and moves to the JIT then runs so something. It's more akin to Python. If you run the script in the Developer console (ctrl+shift+j in Windows) in Chrome it will throw an error but also run to give you the alert.
Sometimes hoisting is explained in a way which may give wrong impression, i.e. the variables and functions are hoisted by JavaScript engine as if they were physically moved on top, which is not actually right, as demonstrated by the code below:
console.log(a);
var a = 'Hello World!';
What we see on console is undefined, not 'Hello World', so we got the behavior of the following code
var a;
console.log(a);
a = 'Hello World!';
not the behavior of
var a = 'Hello World!';
console.log(a);
which you may get the impression from the variables and functions declaration being moved to top statement.
But JavaScript is not actually moving your code anywhere. You need to understand execution context in JavaScript. It has two phases creation phase and execution phase. In creation phase memory space is created for these variables and functions, and people seem to confuse this step with hoisting. JavaScript is actually not moving your code anywhere, what happens is JavaScript has created memory space for all your code i.e. variables and functions, functions can be placed fully in memory but in case of variables the assignments are processed in execution phase of the execution context. So when you do var a = 'Hello World!', JavaScript engine knows the value of a when it starts executing it in execution phase of execution context, so it puts a placeholder undefined, and all variables are initially set to undefined in JavaScript. So it is not good to rely on hoisting and see undefined. So it is always good to declare variables and functions on top of your code.
Section 12.9 (page 75) of ECMA-262 edition 3 states:
An ECMAScript program is considered syntactically incorrect if it contains a return statement that is not within a FunctionBody.
That is, a return outside of a function is a syntax error. If a syntax error occurs, no code is run. Think about your example as if you had written:
alert(myVar1);
return false;
syntax error))))))))))))))))));
In addition, section 16 (page 157) states:
An implementation may treat any instance of the following kinds of runtime errors as a syntax error and therefore
report it early:
Improper uses of return, break, and continue.
Firefox's engine et. al. (i.e. those JavaScript implementations which allow return in the global scope) may be conforming, assuming the following clause (in the same section) allows for implementation definition of return in the global scope:
An implementation shall report all errors as specified, except for the following:
An implementation may provide additional types, values, objects, properties, and functions beyond those described in this specification. This may cause constructs (such as looking up a variable in the global scope) to have implementation-defined behaviour instead of throwing an error (such as ReferenceError).
This code makes little sense:
The var myVar1 will never be ran.
The return false; will not return a thing since you're not in a function
Opera, IE and FF are right to throw an error because this code is really not valid since you're not able to return unless you are in a function.
If it works in Safari and Chrome it must be because the javascript engine they use is ready to handle buggy code. My guess would be that they see the "return" and drop or replace it with some kind of break.
More information about functions: http://www.w3schools.com/js/js_functions.asp
It is JavaScript Hoisting thing, Simply in other words, we are trying print the value of the variable , which is not holding any value
Javascript will render the above code as:-
var myVar1
alert (myVar1)
return false
To clarify more i refered the link javascript hoisting: http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Understanding javascript hoisting and execution context

b();
console.log(a);
var a = 'Hello World';
function b(){
console.log('Called b!');
}
I have read about the term "hoisting", but it isn't pretty clear to me. Why does the function gets executed while the variable is set to undefined?
The interesting part is, the variable didn't show any error. But it showed undefined. But when I remove the variable totally, then it shows an error. That means, the variable is present somewhere though. right?
But if it is present, then why can't the compiler compile it and can compile the function here?
I know that var a is getting hoisted. I want to know why the engine is treating the variable and the function in a different way that is what's happening behind the scenes during the execution context.
Any detailed explanation would be helpful about how the engine is creating the execution context.
In this question I'm asking about how javascript engine is behaving differently with the function and the variable. And what is exactly happening in the creating state and execution state of the execution phase. So, it's not a duplicate question.
But if it is present, then why can't the compiler compile it and can compile the function here?
Basically it boils down to whether the value of the binding can be determined without executing the code or not.
The function declaration itself doesn't depend on runtime information. Keep in mind that the body is not evaluated until the function is called. So even without really executing the code, its clear that the value of b is a function.
However, the initialization value of a variable declaration may depend on runtime information. Consider this:
var a = 10 + bar();
There is no way for the engine to "hoist" the initialization value without evaluating the expression (and executing bar in the process).
Of course in your example, the initialization value ('Hello World') is static as well, so it could be hoisted. But then the behavior would be inconsistent and probably more confusing.
What exactly happens when control enters a new function is defined in the spec. There you can see how variable declarations and function declarations are treated.
With hoisting, this is what your code looks like
function b(){
console.log('Called b!');
}
var a;
b();
console.log(a);
a = 'Hello World';
As you can see, a is declared at the the top, but has not been set to a value yet. That is why you get undefined when you log that variable.
If you remove the a variable altogether, you get the Uncaught ReferenceError because a has not been declared.
The above code is same as below
var a;
function b(){
console.log('Called b!');
}
b();
console.log(a);
a = 'Hello World';
Explanation - Function along with its definition are hoisted to the top. Variable declaration is hoisted not its definition
var a; is hoisted. a = 'Hello World!'; is not hoisted. It's that simple.

Why single var is good in javascript?

Can anyone tell me why use one var declaration for multiple variables and declare each variable on a newline consider is a good programming behavior?
// bad
var items = getItems();
var goSportsTeam = true;
var dragonball = 'z';
// good
var items = getItems(),
goSportsTeam = true,
dragonball = 'z';
It is not considered 'good' or 'bad'. It's a matter of preference.
The guy who built the code quality tool JSLint, Douglas Crockford likes it.
One 'advantage' it might have is that it avoids the possibility of variable hoisting. In JavaScript all var declarations move to the top of their scope automatically.
Here is why Crockford thinks the second option is better:
In languages with block scope, it is usually recommended that variables be declared at the site of first use. But because JavaScript does not have block scope, it is wiser to declare all of a function's variables at the top of the function. It is recommended that a single var statement be used per function. This can be declined with the vars option.
It's a preference, I wouldn't say good or bad. Yes JSLint complains about it, I don't really like how it complains about for loop variables being inline as well. The reason that it was put in JSLint was to prevent possible hoisting confusions.
Also in some cases declaring all of your variables at the top will lead to a slightly smaller file. Consider the following:
var a = 10;
a++;
var b = 20;
After Google Closure being run over it
var a=10;a++;var b=20;
As opposed to this if we pull b's declaration to the top.
var a=10,b;a++;b=20;
The main benefit (aside from style preference, I guess) is that it will prevent you from writing code that suffers from unintended variable hoisting consequences.
Take this example:
var foo = function(){alert('foo');}
function bar(){
foo();
var foo = function(){alert('foobar')};
foo();
}
bar();
By reading this code, the intent of bar appears to be as follows:
Call the outer foo function to alert the string 'foo'.
Create a local variable, foo.
Call the local foo function to alert the string 'foobar'.
In reality, what happens is this:
The local variable foo is hoisted to the top of the bar function.
foo now actually refers to the local variable instead of the outer variable of the same name. But since the local hasn't been assigned yet, its value is undefined. Hence, when you try to invoke foo, you'll get a TypeError.
Nothing. Because you threw an error. That's it. Your code broke.
The arguments for Crockfords preference have been well made and are valid. I am just beginning to return to the first format now however, as I believe that for experienced developers who understand variable hoisting and are not likely to fall foul to it, there are 2 advantages that I can think of:
When new variables are added to the list of definitions, diffing is made easier. This means you are likely to experience fewer merge conflicts (simple though they may be to resolve) and less cognitive load when analysing diffs. For similar reasons I have also been converted to dangling commas, which I would never have expected xD
As #ldsenow identified, it can make searching for variable definitions more simple. You will always be able to search for var <name> and get the result you want and nothing else.

Categories

Resources