Lately, I was studying Scope in Javascript. I want to know whether automatically hoisting is done at compile time or at the time of executing the code(run time). If it does at run time then I have another question does auto-hoisting will slow down the performance of the Javascript program.
something = a();
function a(){
console.log("hoisting");
return 10;
}
var something;
Should we use manual hoisting or it would be better to use automatically hoisting?
To put my comments as an answer:
People have a different understanding of what hoisting supposed to mean. Fact is that, according to the spec, every time a function is called a new execution context is created, which holds a new environment. Then the function body is processed to find all variable declarations (var, let, const (and function declarations)) and bindings for those names are created in the new environment. var declarations are initialized with undefined. Then the body is actually evaluated.
Considering this, from the perspective of the engine it doesn't really matter where you place the var declaration, the whole body has to be processed anyway.
Having said that, I would be surprised if actual implementations didn't cache that information. After all, the variable declarations in a function don't change between function calls.
As I know, There are no performance issues. The initializations are getting done in compile time. So doesn't matter you initialize on top or bottom, The JS engine will create the references in compile time.
BUT
If you forgot to initialize at the bottom, It will be initialized as undefined by default. Because of hoisting it’s considered a practice to declare functions or variables at the top of their respective scopes.
JavaScript: What is Hoisting? (Recommended)
It is not done at run time.
It's in the compile process.
So it doesn't slow down the performance.
Just before the code is executed the compiler scans for all variable and function declarations and allocates them in the memory.
Related
I am studying hard what the closure is in Javascript.
According to MDN, closures are created every time a function is created, at function creation time.
However, many articles and answers in Stack Overflow says that the concept of closure needs the relationship between inner function and outer function and their variables.
So, I wonder whether 'global' is the kind of a function which executes at runtime of global scope(or global execution context) or not.
If 'global' is a function, all of the functions in script are maybe inner functions, I guess.
Please answer me if you are fully understanding closures, and execution contexts. Thank you!
your question is a very genuine one :). What I get from your question is that your confusion is in 'global' in JavaScript. It is not clear from your question if you need help in closures and execution context, so to keep the answer short I'll focus on "global" only.
So global in JavaScript is the global execution context. It is more like complier running the code.
If you have experience in any programming language say Java. You may relate to this. The place where you write functions is not a function itself. So we can safely say global is not a function rather an execution context.
Same way, the functions defined inside a global execution context are not inner functions. They are simply functions.
Maybe you are confused in this, because you feel the variables declared globally can be accessed inside the function declared in global concept, this is simply because of scope of a variable and has nothing to do with closures.
When we execute our code, one of the very first things that the JavaScript engine does is to create a global execution context. This has the same purpose as function execution context, but at the global level with some more particularities. Now, once GEC got created - JS engine moves line by line and starts to execute other functions with their own function execution context!
So as per your question, global is just an execution context that gets created only once at the beginning with some extra features.
Hope this could clear your doubt.
I've been learning a lot of Javascript lately and I've been trying to understand the value (if there is any) of hoisting variables.
I understand (now) that JS is a two pass system, it compiles and then executes. Also, I understand that the var keyword 'exists' in the lexical scope it was declared, hence why it's 'undefined' if it's called before it's assigned a value by the engine.
The question is, why does that even matter? What use is there to hoisting variables that you can't do without hoisting? I feel like it just creates less-readable code with no gain ...
is there an example(s) of where hoisting variables is useful?
"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);
};
}
};
Not really. The only thing I can think of where it would be helpful is if you are writing code in a hurry and you happen to declare it later on. So it doesn't really matter, it's a weird addition to JS that a lot of people don't really even know about because utilizing it feels backwards and inefficient.
There is no such thing as hoisting. Hoisting is merely a side effect of the compile phase that occurs and the fact that Javascript is lexically scoped. When the compiler comes to the compile phase it puts all variable and function declarations in memory as it figures out the lexical scopes that exists in the program. But there is no hoisting function or keyword or module. In fact it wasn't even reference in the Ecmascript spec before the es2015 release.
At the end of the day, hoisting is one of those million dollar words we all use, often because its easier to use rather than explain and discuss the compilation process that javascript goes through.
My suggestion would be to either read through the Ecmascript specs, work through a javascript engine source like v8, or read up on Kyle Simpson's work. He wrote a great series called You Don't Know JS.
Hope this helps!
Hoisting is a term you will not find used in any normative specification prose prior to ECMAScript® 2015 Language Specification. Hoisting was thought up as a general way of thinking about how execution contexts (specifically the creation and execution phases) work in JavaScript. However, the concept can be a little confusing at first.
Conceptually, for example, a strict definition of hoisting suggests that variable and function declarations are physically moved to the top of your code, but this is not in fact what happens. Instead, the variable and function declarations are put into memory during the compile phase, but stay exactly where you typed them in your code. <- From the Mozilla docs
https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
The ES6 standard comes up with Temporal Dead Zones, making a variable reference not possible in any way until the lexical binding is evaluated. So what does variable creation at the time of lexical environment initialisation mean to
The programmer ?
The Compiler ?
The declaration of a variable using var declaration might mean something to the programmer previously, but now with TDZ in place does javascript start behaving like java for this purpose? Is there any reason other than the way javascript interpreter works that we have hoisting (as a result TDZ) in the first place?
What happens when a lexical binding is encountered later in the code due to order of execution even when the code appears before it lexically?
let abc = f();
let b;
f(){ return b;}
When does traditionally programming languages like java create variables? When the variable declaration is encountered? or when the lexical scope is initialised?
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.
So what does variable creation at the time of lexical environment
initialisation mean to the programmer?
Not much. A programmer only intends to use declared and initialised variables.
That the variable is available in the whole scope (from the beginning) only means that mistakes will be caught easier, as the usage of the variable prior to initialisation fails (with an exception) instead of silently being resolved to an outer-scope (global?) variable. It also means that the identifier, regardless where in the scope it is used, always refers to the local variable - which is just what we'd expect from a scope.
So what does variable creation at the time of lexical environment
initialisation mean to the Compiler?
That a lexical environment doesn't change its structure during execution. Static resolution of identifiers in a known scope makes compiling possible, and execution faster.
Just as a counterexample, consider this thing:
var x = "global";
var code = "var x = 'local';";
(function() {
"use sloppy";
function test() {
console.log(x); // what do you think does `x` refer to?
} // It's hard to understand as a developer,
// now imagine being a compiler that tries to optimise `test`.
test();
eval(code);
test();
}());
What happens when a lexical binding is encountered later in the code
due to order of execution even when the code appears before it lexically?
b is used by the call to f() before it's initialised. Accessing it throws a TDZ exception.
You can try it online.
Does any one know about optimization effects of passing in a variable via function arguments versus having the variable available via a closure? It seems like passing in variables via function arguments would be faster since objects are copied by reference (so fast copy time) and climbing the scope environments of the function requires checking the environment at each level. Here's the gist of what I mean
a = 5;
b = function() {
alert(a);
}
b();
versus
a = 5;
b = function(c) {
alert(c);
}
b(a);
Which in theory performs faster?
I had the same question a little while ago, so I slapped together a quick'n'dirty benchmark. It appears that most popular browsers (surprisingly) prefer looking up in the scope (FF24 very much so).
I hope this answers your question.
climbing the scope environments of the function requires checking the environment at each level
Only theoretically. In fact, since the scope chain is not dynamic, this can and will be optimized to a static reference.
passing in variables via function arguments would be faster since objects are copied by reference (so fast copy time)
Even it is very fast, they still need to be copied. The function needs to allocate extra memory for them, while the reference to the closure does not anything like that.
If you can put a value in the closure scope, do it. It's only practical, you want to build a closure. If you don't want and need variable arguments in your function, use parameters. Use the more readable alternative.
It all depends. Don't worry about it unless it's a big issue in the future.
I have read, and discovered through my own experience, that JavaScript doesn't have a block scope. Assuming that the language was designed this way for a reason, can you explain to me what is that reason?
I've looked around on Google and here, but the posts I have found just reiterate that JS has a function scope and not block scope, without explaining why. I'm curious to know why this is actually the case.
Converting my comment to answer
Choice of the creator: I tweeted Brendan and got the following answer:
#mplungjan 10 days did not leave time for block scope. Also many "scripting languages" of that mid-90s era had few scopes & grew more later.
That said, here are some relevant points:
Block statement
Important: JavaScript prior to ECMAScript2015 (6th edition) does not have block scope. Variables introduced within a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java.
a workaround
we can artificially introduce scopes by creating new functions and immediately invoking them
ECMAScript 2015 (ES6)
let and const declared variables are hoisted but they are not initialized to undefined in the same way var is. Hence, referencing a let or const declared variable before its value is assigned raises a ReferenceError.
Redeclaration of the same variable in the same block scope raises a SyntaxError.
New answer as of 2015. ES6 does have block scope for variable definitions with the let and const keywords.
Block scope was not implemented for the following reasons:
It's makes the language easier to implement. JavaScript was initially designed as a language for writing interactive web applications. Hence it needed to be small and easy to implement.
Block scopes introduce a performance hit to dynamic languages like JavaScript. This is because when you try to access some variable which is not in the current scope JavaScript first checks the current scope, then the parent scope and so on until it either finds the variable or reaches the end. Hence the introduction of block scopes would make variable access in loops and nested loops very slow.
The lack of block scopes makes it easier to write programs. For example say you want to create a variable only if a certain condition is true. All you need to do in JavaScript is declare and define the variable within an if statement. In languages like C you would have to declare the variable outside the if statement and define it within the if statement.
The lack of block scopes allow declarations to be hoisted. This is especially useful in the case of function declarations. For example see this fiddle: http://jsfiddle.net/L6SgM/ (note however that this example doesn't work in Firefox).
Since JavaScript supports first-class function expressions we don't need block scopes. They can be simulated using immediately invoked function expressions.
There are many reasons, but some that come to mind are to aid in parsing/debugging code that uses object literals (which can sometimes look like a block), and to simplify the garbage collection of local variables.
I hope that the promised support (discussed here, for example, http://esdiscuss.org/notes/2012-07-25) turns out to be real because it would be very convenient to use variables like i that were local to only a single loop.