-5

var name = 'ali'
function sayHi() {
  console.log(name);
  console.log(age);
  var name = 'Lydia';
  let age = 21;
}

sayHi()

When i put this code AST explorer and run it. I actually see that name has already been assigned to variable 'Lydia' before the code is executed.I know AST is created before the code is run . But when the code is executed it returns undefined. I am very confused about this please can you help me

rici
  • 234,347
  • 28
  • 237
  • 341
ikarus
  • 11
  • 3
  • Add `"use strict;"` above it all and JavaScript should throw a ReferenceError: Cannot access 'age' before initialization. – Heretic Monkey Jan 08 '21 at 23:20
  • @HereticMonkey I know this I'm wondering why the value throw eror when abstract syntax tree already knows the value – ikarus Jan 08 '21 at 23:22
  • Because that's what ECMAScript defines should happen if an attempt is made to get a variable defined using `let` (or `const`). – Heretic Monkey Jan 08 '21 at 23:26
  • I cant send images . But can you paste this code on site and look please https://astexplorer.net/ – ikarus Jan 08 '21 at 23:26
  • 2
    I don't need to. I don't care what some site that doesn't know the rules of ECMAScript says should happen. Once ECMAScript rules kick in, it doesn't matter that the AST "knows" something. The rules say if you try to access it, an error is thrown. So when you try to access it, an error is thrown. – Heretic Monkey Jan 08 '21 at 23:29
  • Hi @ikarus, thanks for posting! May be helpful to add a link to the source you're using with the original question. Abstract syntax trees are exactly as they are named, abstracted from syntax. The link you cited applies specific syntax depending on the language being parsed or interpreted, and the question relates to Javascript syntax specifically so an AST wouldn't be applicable. – Jacob Harding Jan 13 '21 at 03:52

1 Answers1

0

There are two variables with the same name (name) in that snippet. If you look closely at the generated AST, you will see both declarations.

The AST does not show the scopes of the two declarations, which is an important aspect. The scope of a variable is the region of the program in which the variable's name is visible; that is, associated with the variable. It is perfectly legal for two variables to have the same name; if they have overlapping scopes, the inner scope will override the outer scope.

All of that is common to most programming languages, but ECMAScript's scoping rules are rather more complicated than average (which, in part, is why it would be useful for the AST tool to show scopes). ECMAScript features two different sets of scoping rules, one for variables declared with var, and another for variables declared with let or const.

While this simple example doesn't show all the differences, it certainly does show one important difference: while the inner var-declared name can be used before it has been initialised, resulting in the value undefined, the let-declared age cannot be used before initialisation, resulting in an error being thrown. (let-declared variables are in what's called a "Temporal Dead Zone" until they are initialised.)

The difference which is not shown in this example is the boundaries of the scopes of the variables declared inside the function sayHi. The scope of a var-declared variable is the innermost function body which it is declared in (including any functions declared in the same scope, unless they have an overriding declaration of the same name). The scope of a let-declared variable, on the other hand, is limited to the innermost enclosing block. But in this example, the innermost enclosing block of both the inner var name and let age is the body of the function sayHi.

In ECMAScript, the scope of a variable is always an entire block. This contrasts with languages such as C in which the scope of a variable only extends from the variable's declaration until the end of the enclosing block. This would make a difference in this case: Under C scoping rules, name in console.log(name) would refer to the outer declaration, because the inner declaration is further down in the code and so its scope hasn't started yet. And age in console.log(age) would be illegal because there is no enclosing scope in which age is declared. But in ECMAScript, declarations are "hoisted" to encompass the entire block, creating the possibility of Temporal Dead Zones.

While this is probably already Too Much Information, I should note that I haven't really covered all of the odd wrinkles in scoping in either ECMAScript or C, and that other languages have other subtly different scoping rules.

rici
  • 234,347
  • 28
  • 237
  • 341