Why Does JavaScript Hoist Variables

Why does JavaScript hoist variables?

As Stoyan Stefanov explains in "JavaScript Patterns" book, the hoisting is result of JavaScript interpreter implementation.

The JS code interpretation performed in two passes. During the first pass, the interpreter processes variable and function declarations.

The second pass is the actual code execution step. The interpreter processes function expressions and undeclared variables.

Thus, we can use the "hoisting" concept to describe such behavior.

Is there a purpose to hoisting variables?

"Hoisting" is necessary for mutually recursive functions (and everything else that uses variable references in a circular manner):

function even(n) { return n == 0 || !odd(n-1); }
function odd(n) { return !even(n-1); }

Without "hoisting", the odd function would not be in scope for the even function. Languages that don't support it require forward declarations instead, which don't fit into JavaScripts language design.

Situations that require them might arise more often that you'd think:

const a = {
start(button) {

button.onclick = e => {

b.start(button);
};
}
};
const b = {
start(button) {

button.onclick = e => {

a.start(button);
};
}
};

Is there any benefit from hoisting?

The main benefit of hoisting is that functions don't have to be declared in a specific order in order to work properly. The interpreter makes a pass over a function of code and finds all the function declarations within that function and makes them available to code anywhere in the scope (hoisting them) whether the code referring to the functions is before or after where the function declarations are located. It also allows A to call B and B to call A without running into declaration ordering issues.

Variable hoisting is rarely used anymore now that we have const and let which are block scoped and cannot be used before declaration. So hoisting is mainly useful for function declarations now.

How JS hoisting works within functions?

JavaScript hoisting within functions means that the declaration of variables are moved to the top of the function block. When you enter foo(), var boo is redeclared instantly even though you have not reached it (because the JS engine knows that this declaration exists within the function). Accordingly, the reason that it is undefined is because it has only been declared, you don't assign a value until the following line.

In reality, this is not a situation you should find yourself in if you declare variables in an appropriate scope and don't redeclare variables with the same name, but I understand your curiosity.

You can read more about this here.

javascript hoisting: what would be hoisted first — variable or function?

Given var foo = something, only the variable declaration is hoisted.

This means that var foo is hoisted but the foo = something will run in the reading order.

Given function foo() {}, the variable declaration and function assignment are both hoisted. This creates the variable foo and gives it the value of the function.

If you have both of the above, then you declare the variable twice (for no extra effect) and assign it the value of the function (as that is the only assignment).

So in your second example…

The function declaration is hoisted, so f(); // - first f calls that.

The assignment of the function expression is not hoisted, but f(); // ** - second f appears after it in normal reading order, so the second call to foo() hits that.

Why hoist variables when there is TDZ

I have a feeling that the creation of TDZ had to do with it being a very menial step from var, whereas if they were to go with the seemingly more logical approach of not even having the identifier exist, the engine would have had to undergo even more intensive changes. As for the second part of your question in reference to when other languages "create" variables, there are many other important factors to consider that you seem to have left out, such as is the language interpreted vs compiled, as well as there are multiple different steps to "creating" a variable. It acts differently in many different cases, and there is no single answer. In fact, that is one of the big reasons why there are many different languages.

As for your coding question, it would depend on when you're calling your f function, since function declarations are hoisted in javascript. If you are calling it before b is declared, then you are in a TDZ and b cannot be referenced. It will behave very similarly as if you were simply putting the return b wherever this function is called.

Honestly, it seems as if there is some underlying misunderstanding of javascript, and computer languages in general. Javascript is not "behaving" more like java, in fact the new let keyword has very nuanced behavior, such as being able to be block scoped, compared to type/variable declarations in java. I would suggest not trying to think of the changes in ES6 in terms of other languages; javascript is not like a lot of other languages, it will be very difficult to understand the concepts and how you should be programming with javascript if you do.


EDIT:

As for why there is variable and function declaration hoisting, that is easily googlable.



Related Topics



Leave a reply



Submit