New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does `const` declaration is subject to the Variable Hoisting? #1132

Closed
Konrud opened this Issue Aug 29, 2017 · 16 comments

Comments

Projects
None yet
6 participants
@Konrud

Konrud commented Aug 29, 2017

From ES6 & Beyond - Chapter 2: Syntax I couldn't understand whether const declaration is subject to the variable hoisting?

example:

;(function () {
    "use strict";

     const x = 3;

     function foo() {
         console.log("const x: ", x);
         console.log("const y: ", y);
     };

     const y = 5;

     foo();

})();

In the example above function foo is declared before const y declaration so according to Scope & Closures - Chapter 2: Lexical Scope which states that: "No matter where a function is invoked from, or even how it is invoked, its lexical scope is only defined by where the function was declared." foo should throw an error when it's called, but in this example when foo is called it does log x and y values. So how does it possible if const does not hoisted.

@artiegold

This comment has been minimized.

Show comment
Hide comment
@artiegold

artiegold Aug 29, 2017

artiegold commented Aug 29, 2017

@getify

This comment has been minimized.

Show comment
Hide comment
@getify

getify Aug 29, 2017

Owner

This example isn't actually about hoisting at all. You don't call foo() until after you've declared and initialized y, so obviously y is in the scope when foo() runs.


If you reverse those two lines, you'll see you get a ReferenceError error, commonly referred to as a TDZ (temporal dead zone) error.

It is commonly cited that let and const don't "hoist", but this is an inaccurate statement. Hoisting (a made up metaphor, not a real thing) describes the notion that a variable's binding is added to a lexical scope at the time the lexical scope is entered. In all of var, let, and const, this is true.

The difference between var and the other two (let, const) is not that they don't "hoist". Rather, var initializes (to undefined) its variable at the time the lexical scope is entered, whereas let and const defer the initialization until the actual declaration statements are encountered.

A variable that has not been initialized (to undefined) in a lexical scope is said to be in its TDZ, and thus cannot be accessed yet.

IOW, let and const declarations do in fact "hoist" their variable declarations to the entire enclosing scope (just like var), but they remain uninitialized (unlike var) and thus cannot be accessed earlier (from an execution perspective, not a code location perspective) in the scope than their declaration point.

Owner

getify commented Aug 29, 2017

This example isn't actually about hoisting at all. You don't call foo() until after you've declared and initialized y, so obviously y is in the scope when foo() runs.


If you reverse those two lines, you'll see you get a ReferenceError error, commonly referred to as a TDZ (temporal dead zone) error.

It is commonly cited that let and const don't "hoist", but this is an inaccurate statement. Hoisting (a made up metaphor, not a real thing) describes the notion that a variable's binding is added to a lexical scope at the time the lexical scope is entered. In all of var, let, and const, this is true.

The difference between var and the other two (let, const) is not that they don't "hoist". Rather, var initializes (to undefined) its variable at the time the lexical scope is entered, whereas let and const defer the initialization until the actual declaration statements are encountered.

A variable that has not been initialized (to undefined) in a lexical scope is said to be in its TDZ, and thus cannot be accessed yet.

IOW, let and const declarations do in fact "hoist" their variable declarations to the entire enclosing scope (just like var), but they remain uninitialized (unlike var) and thus cannot be accessed earlier (from an execution perspective, not a code location perspective) in the scope than their declaration point.

@Konrud

This comment has been minimized.

Show comment
Hide comment
@Konrud

Konrud Aug 29, 2017

@artiegold Thanks for your answer but if what you are saying is true, then const should not be defined when it hoisted. In Scope & Closures - Chapter 2 Lexical Scope there is a statement that: "....functions are hoisted first, and then variables." so when the function is declared it can't see the const variable because it's declared afterwards.
Moreover, if you take a look a const/let explanation in MDN you will find that: "In ECMAScript 2015, let bindings are not subject to Variable Hoisting, which means that let declarations do not move to the top of the current execution context." (const / let)

like so:

;(function () {
   "use strict";

    function foo() { // hoisted
        console.log("const x: ", x);
        console.log("const y: ", y);
    };

    const x = 3; // hoisted (unlikely)
    const y = 5; // hoisted (unlikely)

 .
 .
 .

})();

Konrud commented Aug 29, 2017

@artiegold Thanks for your answer but if what you are saying is true, then const should not be defined when it hoisted. In Scope & Closures - Chapter 2 Lexical Scope there is a statement that: "....functions are hoisted first, and then variables." so when the function is declared it can't see the const variable because it's declared afterwards.
Moreover, if you take a look a const/let explanation in MDN you will find that: "In ECMAScript 2015, let bindings are not subject to Variable Hoisting, which means that let declarations do not move to the top of the current execution context." (const / let)

like so:

;(function () {
   "use strict";

    function foo() { // hoisted
        console.log("const x: ", x);
        console.log("const y: ", y);
    };

    const x = 3; // hoisted (unlikely)
    const y = 5; // hoisted (unlikely)

 .
 .
 .

})();
@getify

This comment has been minimized.

Show comment
Hide comment
@getify

getify Aug 29, 2017

Owner

MDN is wrong.

Owner

getify commented Aug 29, 2017

MDN is wrong.

@getify

This comment has been minimized.

Show comment
Hide comment
@getify

getify Aug 29, 2017

Owner

when the function is declared it can't see the const variable because it's declared afterwards.

That's just not how lexical scoping works. The order of declaration of a function versus a var, let, or const is not relevant, as the observation of a binding doesn't happen until run time. The order of execution is the important part.

Owner

getify commented Aug 29, 2017

when the function is declared it can't see the const variable because it's declared afterwards.

That's just not how lexical scoping works. The order of declaration of a function versus a var, let, or const is not relevant, as the observation of a binding doesn't happen until run time. The order of execution is the important part.

@Konrud

This comment has been minimized.

Show comment
Hide comment
@Konrud

Konrud Aug 29, 2017

@getify but what about Scope & Closures - Chapter 2: Lexical Scope which states that: "No matter where a function is invoked from, or even how it is invoked, its lexical scope is only defined by where the function was declared." ? Doesn't it mean that foo is declared before so it can't see const y?

Konrud commented Aug 29, 2017

@getify but what about Scope & Closures - Chapter 2: Lexical Scope which states that: "No matter where a function is invoked from, or even how it is invoked, its lexical scope is only defined by where the function was declared." ? Doesn't it mean that foo is declared before so it can't see const y?

@getify

This comment has been minimized.

Show comment
Hide comment
@getify

getify Aug 29, 2017

Owner

That statement is referring to the scope as a whole, meaning if one function is inside another, then that inner function's scope is entirely determined by that location. It doesn't mean where inside that outer function it's declared, only that it's inside.

Owner

getify commented Aug 29, 2017

That statement is referring to the scope as a whole, meaning if one function is inside another, then that inner function's scope is entirely determined by that location. It doesn't mean where inside that outer function it's declared, only that it's inside.

@Konrud

This comment has been minimized.

Show comment
Hide comment
@Konrud

Konrud Aug 29, 2017

In "... the notion that a variable's binding is added to a lexical scope at the time the lexical scope is entered." what do you mean by variable's binding ?

Konrud commented Aug 29, 2017

In "... the notion that a variable's binding is added to a lexical scope at the time the lexical scope is entered." what do you mean by variable's binding ?

@getify

This comment has been minimized.

Show comment
Hide comment
@getify

getify Aug 29, 2017

Owner

The attachment of a variable to a scope.

Owner

getify commented Aug 29, 2017

The attachment of a variable to a scope.

@justsml

This comment has been minimized.

Show comment
Hide comment
@justsml

justsml Aug 29, 2017

So if a let falls in the forest, it only makes a noise if its been set?

(Thanks @getify, the mdn description didn't seem correct.)

justsml commented Aug 29, 2017

So if a let falls in the forest, it only makes a noise if its been set?

(Thanks @getify, the mdn description didn't seem correct.)

@akras14

This comment has been minimized.

Show comment
Hide comment
@akras14

akras14 Aug 29, 2017

I asked on twitter, but let me follow up here.

Do let and const "hoist" to the top of block scope (i.e. If statement) or will they hoist to the top of the inner most function?

akras14 commented Aug 29, 2017

I asked on twitter, but let me follow up here.

Do let and const "hoist" to the top of block scope (i.e. If statement) or will they hoist to the top of the inner most function?

@getify

This comment has been minimized.

Show comment
Hide comment
@getify

getify Aug 29, 2017

Owner

@akras14 yes, let and const attach to the nearest enclosing block (aka lexical scope environment) whereas var attaches to the nearest enclosing function (also a lexical scope environment).

Owner

getify commented Aug 29, 2017

@akras14 yes, let and const attach to the nearest enclosing block (aka lexical scope environment) whereas var attaches to the nearest enclosing function (also a lexical scope environment).

@ithacasnowman

This comment has been minimized.

Show comment
Hide comment
@ithacasnowman

ithacasnowman Mar 7, 2018

@getify The following statement from Scope & Closures Chapter 3:

However, declarations made with let will not hoist to the entire scope of the block they appear in.

contradicts a previous comment of yours:

IOW, let and const declarations do in fact "hoist" their variable declarations to the entire enclosing scope (just like var)...

ithacasnowman commented Mar 7, 2018

@getify The following statement from Scope & Closures Chapter 3:

However, declarations made with let will not hoist to the entire scope of the block they appear in.

contradicts a previous comment of yours:

IOW, let and const declarations do in fact "hoist" their variable declarations to the entire enclosing scope (just like var)...

@getify

This comment has been minimized.

Show comment
Hide comment
@getify

getify Mar 7, 2018

Owner

the "scope & closures" book was written almost 2 years earlier than the ES6 book. my understanding evolved and improved over that period. and also ES6 itself settled and finalized.

Owner

getify commented Mar 7, 2018

the "scope & closures" book was written almost 2 years earlier than the ES6 book. my understanding evolved and improved over that period. and also ES6 itself settled and finalized.

@ithacasnowman

This comment has been minimized.

Show comment
Hide comment
@ithacasnowman

ithacasnowman Mar 7, 2018

Were you planning on fixing those mistakes? It almost sounds like you were already aware of this issue.

ithacasnowman commented Mar 7, 2018

Were you planning on fixing those mistakes? It almost sounds like you were already aware of this issue.

@getify

This comment has been minimized.

Show comment
Hide comment
@getify

getify Mar 7, 2018

Owner

I am aware of the issue. Yes it's planned for being addressed in the second edition (whenever that happens!). :)

Owner

getify commented Mar 7, 2018

I am aware of the issue. Yes it's planned for being addressed in the second edition (whenever that happens!). :)

@getify getify closed this Mar 18, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment