Does Hoisting occur with the variable within the function or any other block command?

Asked

Viewed 97 times

5

Keyword variable statements var does not directly have a local scope its scope is within the function that contains it or outside it the scope is global (var Hoisting).

Like in the example below the variable n1 will be raised to the top of the execution context which is the function test() and in that case it will be visible throughout the function test():

function test() {
    if (10 == 10) {
        var n1 = 450;
    }
    
    console.log(n1); // 450
}

test();

But what if, for example, instead of using the keyword var, i use the keyword let or const then the scope will no longer be the function test() but the command if and the variable n1 will be visible only inside the command if, if you try to use it outside of this an error is returned:

function test() {
    if (10 == 10) {
        let n1 = 450;
    }
    
    console.log(n1); // Será retornado erro.
}

test();

In the case of the above example I can say that it occurred Hoisting with the variable n1? because it has been moved to the execution context that contains it in case it is no longer the function test() but the command if, this can be considered Hoisting or not?

  • @bfavaretto, I just found a MDN article saying that Hoisting de Let is raised to the block containing https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Block_scoping

  • That was my question.

  • 1

    @bfavaretto is perhaps because at the time ES6 was not yet implemented in the browser(?). Now testing the same code as my question the error is another: Uncaught ReferenceError: Cannot access 'foo' before initialization. That is, the Hoisting occurs, but the variable is inaccessible before the declaration.

  • The Hoisting with var is raised to the function containing it. Already variables declared with let or const the Hoisting will be the block that was set it. At least that’s what I understood :)

  • 1

    @bfavaretto On the other hand, if ES6 were not available in the browser, it would error the let. Then I don’t remember anymore. It may be that I informed the wrong error in the question, I don’t remember. I think this is most likely, because in 2018 Chrome already had ES6 support.

  • 3

    Debatable is it possible to call Hoisting the recognition of the variable during the "temporal déad zone", as they say, only to make an exception. In practice there is no Hoisting, there is no way to access the variable without initializing.

  • 4

    @ledevwd This MDN content in pt_BR is wrong!

  • @bfavaretto, but Hoisting is not Hoisting when the variable is raised to the scope that contains itself and is visible within that scope or necessarily must be possible to access the variable before it has even been declared to be considered Hoisting?

  • 2

    This answers your question? How Hoisting Works at ES6?

  • @Sam had already mentioned the link of this question, I read it and also the links of the questions cited in the comments, but it was not clear to me.

  • 2

    @ledevwd "Hoisting" is not such a precise term. I don’t see it being used to describe the behavior of let, only that of var (and function parameters and function names, see details here). And the fact is that in these cases it is possible to access the variable before the point where it is declared. In the case of let, clearly the JS interpreter needs to know that it exists to cast the exception, but me I wouldn’t call it Hoisting, because it’s not the same thing and it might confuse

  • 3

    @bfavaretto had already reported in feedback on the link to Mozilla but it did not take effect until today.

  • @Eliseub. several translations on MDN are outdated or simply wrong, the same happens with the site of microsoft MSDN, in C# some time the Bfavareto even noticed something wrong in my reply, when I checked it was error that I copied from the documentation in Portuguese, in PHP also several pages in Portuguese are outdated or wrong, for this reason I am avoiding as much as possible any content of doc in Portuguese, both in replies and comments on the site.

  • @Guilhermenascimento and I do not take your reason, you have more experience and know-how and if you made this decision is because it makes a difference, I noticed some incongruities in the documentation of CSS3 of W3C but also did not get back, I am studying PHP and I have a foot behind, there I consult the official documentation, but I get lost there.

Show 9 more comments

3 answers

4


In the case of the above example can I say that Hoisting occurred with the variable n1? this because it has been moved to the execution context that contains it in case it is no longer the test() function but the if command, this can be considered Hoisting or not?

No, the creation of the variable was not moved in its example. It was declared within the if, and that is where it exists, and only there, and only from the moment it is declared. That is, it is not available for use even within the same block, before the line where it is declared. So I consider that there is no Hoisting. Hoisting is the expression used to describe the behavior opposite to this, that is, the scope behavior of the var, arguments of appointed functions and functions (more details in this my answer).

4

In the first example, you are using var, which is an old way of declaring variables in Javascript. It can be said that there are Hoisting in var, since the declaration will be elevated to the most internal function in which it was declared, and not to the block.

Consider the example below:

function outer() {
  function inner() {
    console.log(myVar); // undefined

    if (true) {
      var myVar = 500;
    }
    
    console.log(myVar); // 500
  }
  
  inner();
  // console.log(myVar); -> Isso lançaria um erro.
}

outer();

One can say, then, which variables declared with var have the accessible declaration within the innermost function in which they were declared. Therefore, variables var have the scope of function and not block. They also have the so-called Hoisting. You can learn more about this in this reply from @bfavaretto.

It is also worth noting that the statement was moved to the beginning of inner, and not to the beginning of outer, since the variable was declared within the function inner, and not outer. In that case, inner is the nearest internal function.


On the other hand, variables declared using let or const have the scope of block. I do not know if I can, however, say that they do not possess Hoisting, since even the Ecmascript specification is a little vague regarding this. See:

let and const declarations define variables that are scoped to the running Execution context’s Lexicalenvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable’s Lexicalbinding is evaluated. A variable defined by a Lexicalbinding with an Initializer is Assigned the value of its Initializer’s Assignmentexpression when the Lexicalbinding is evaluated, not when the variable is created. If a Lexicalbinding in a let declaration does not have an Initializer the variable is Assigned the value Undefined when the Lexicalbinding is evaluated.

Own emphasis. Source.

The above section does not say at any time that let or const do not have Hoisting, but makes it clear that, as in the bold section, "the variables are created when their lexical environments are instantiated, but cannot be accessed in any way until their Lexicalbinding is evaluated". This means that the variables that used this declaration cannot be accessed before their value has been evaluated.

So there is a "temporal Dead zone" (see here or here). It prevents variables declared with let or const can be read until your value is assigned. This is because if you try to access a variable let or const before your value is assigned, you will receive a ReferenceError. Behold:

console.log(x); // ReferenceError
let x = 10;
console.log(x);

To learn more, read the links placed during this reply.

Reference:

  • 2

    Great answer!

3

I would say that occurred Hoisting in code with var, since the variable was "raised" to the function scope.
When declared with var, the variables either have global scope or the scope of the function that has been declared and is at this time occurs the Hoisting.
already in statements with const or let, the variable becomes available only to the scope in which it was declared, be it a function, a control structure, or a repetition structure. That’s why in the code with let an error occurs.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.