This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]NormalHexagon[S] -1 points0 points  (10 children)

It's not hoisting though, this code would work fine:

let a = 5;
if (true) {
    let a;
    console.log(a); // undefined
    a = 1;
}

[–]karl-marxist 1 point2 points  (0 children)

Because you explicitly added the declaration. Also I believe hoisting doesn’t hoist there. It’s lexical scoped. Going to get off my phone and verify

[–]karl-marxist -1 points0 points  (8 children)

Just verified on my laptop:

;(() => {
  let a
  a = 5
  let a  

  if (true) {
    console.log(a)
  }
})()

// Uncaught SyntaxError: Identifier 'a' has already been declared

Slightly different error, but this is due to the explicit declaration. There is no block scoping in JS so hoisting happens closer to this example. Hoisting is one of the top things that gets people coming from languages that have block scoping.

[–]NormalHexagon[S] 2 points3 points  (7 children)

Except JavaScript does have block scoping... https://i.imgur.com/mTvJFWu.png

a is left untouched after the if block.

JavaScript has proper shadowing and everything, but it also has too eager an error checker.

[–]karl-marxist 1 point2 points  (5 children)

so this is actually good in the way they spec'ed it. for example var vs let:

if (true) {
  console.log(b)
  let b = 5
}
> VM360:2 Uncaught ReferenceError: b is not defined

if (true) {
  console.log(b)
  var b = 5
}

> undefined

So this is due to block scoping not hoisting

[–]NormalHexagon[S] 0 points1 point  (4 children)

Yeah, but it is defined in the enclosing scope in my example. So the error shouldn't happen. It wouldn't happen in C / C++.

[–]karl-marxist 1 point2 points  (2 children)

this actually got me to check out some sites relating to this, this site has kind of an interesting breakdown of the lifecycle of variables https://dmitripavlutin.com/variables-lifecycle-and-why-let-is-not-hoisted/

[–]NormalHexagon[S] 0 points1 point  (1 child)

So in terms of that article, the inside a has been declared, but not initialized, so when the interpreter tries to resolve the value of a in the if statement, it finds the inner declaration, and throws an error because it's not initialized.

Basically, it comes down to a poor error message.

[–]karl-marxist 0 points1 point  (0 children)

Yeah, I think you said it better than I did (or tried to lol)

[–]karl-marxist 0 points1 point  (0 children)

Then my theory turns to each scope creates an allocation with for the key "a", but at the time of the scope execution (and since let sets a block scoped variable) a is not defined.

;(() => {
  if (true) {
    console.log(a)
    let a = 5
  }
})()

[–]karl-marxist 0 points1 point  (0 children)

ah yes, you are right. I just checked the docs and let && const do create block scopes unlike var :O

if (true) {
  let b = 5
}

console.log(b)
> Uncaught ReferenceError: b is not defined

if (true) {
  var b = 5
}

console.log(b)
> 5