Scopes are determined during compilation based on where the functions/blocks of scope are written, the nesting inside each other, and so on.Įach scope bubble is entirely contained within its parent scope bubble-a scope is never partially in two different outer scopes. So while our previous snippets were simplified in that they only included global scope, the foo(.) function we are now examining itself exhibits that var a is hoisted to the top of foo(.) (not, obviously, to the top of the program).The term "lexical" refers to the first stage of compilation (lexing/parsing). It's also important to note that hoisting is per-scope.
![you dont know js scopes and closures you dont know js scopes and closures](https://miro.medium.com/max/6436/1*7UAKs86_jTQGWe-Ieqr2qQ.jpeg)
The function foo's declaration (which in this case includes the implied value of it as an actual function) is hoisted, such that the call on the first line is able to execute. If hoisting were to re-arrange the executable logic of our code, that could wreak havoc.
![you dont know js scopes and closures you dont know js scopes and closures](http://won.webknit.co.uk/wp-content/uploads/2017/03/you-dont-know-js.jpg)
Note: Only the declarations themselves are hoisted, while any assignments or other executable logic are left in place. In other words, the egg (declaration) comes before the chicken (assignment).
You dont know js scopes and closures code#
So, one way of thinking, sort of metaphorically, about this process, is that variable and function declarations are "moved" from where they appear in the flow of the code to the top of the code. Similarly, our second snippet is actually processed as: var a where the first part is the compilation and the second part is the execution. Our first snippet then should be thought of as being handled like this: var a The second statement, the assignment, is left in place for the execution phase. The first statement, the declaration, is processed during the compilation phase. But JavaScript actually thinks of it as two statements: var a and a = 2. When you see var a = 2, you probably think of that as one statement. So, the best way to think about things is that all declarations, both variables and functions, are processed first, before any part of your code is executed. Chapter 2 showed us that this is the heart of Lexical Scope. Part of the compilation phase was to find and associate all declarations with their appropriate scopes. Recall that the Engine actually will compile your JavaScript code before it interprets it. To answer this question, we need to refer back to Chapter 1, and our discussion of compilers. Which comes first, the declaration ("egg"), or the assignment ("chicken")? The Compiler Strikes Again So, what's going on here? It would appear we have a chicken-and-the-egg question. Unfortunately, both guesses are incorrect. Others may think that since the a variable is used before it is declared, this must result in a ReferenceError being thrown. You might be tempted to assume that, since the previous snippet exhibited some less-than-top-down looking behavior, perhaps in this snippet, 2 will also be printed. However, the output will be 2.Ĭonsider another piece of code: console.log( a ) Many developers would expect undefined, since the var a statement comes after the a = 2, and it would seem natural to assume that the variable is re-defined, and thus assigned the default undefined. What do you expect to be printed in the console.log(.) statement? While that is substantially true, there's one part of that assumption which can lead to incorrect thinking about your program. There's a temptation to think that all of the code you see in a JavaScript program is interpreted line-by-line, top-down in order, as the program executes.
![you dont know js scopes and closures you dont know js scopes and closures](https://ebook2book.ir/wp-content/uploads/2021/06/9798621536459-768x767.jpg)
Both function scope and block scope behave by the same rules in this regard: any variable declared within a scope is attached to that scope.īut there's a subtle detail of how scope attachment works with declarations that appear in various locations within a scope, and that detail is what we will examine here. You Don't Know JS: Scope & Closures Chapter 4: Hoistingīy now, you should be fairly comfortable with the idea of scope, and how variables are attached to different levels of scope depending on where and how they are declared.