- Can anyone explain why
testVariable has two different ouputs when using let. And why there isn't any runtime error when varibles with the same name are defined in window object?
Object.defineProperty(window, 'testVariable', {
value: 22
})
let testVariable = 12
console.log(window.testVariable) // result: 22
console.log(testVariable) // result: 12
- But when using
var, the outputs are the same.
Object.defineProperty(window, 'testVariable', {
value: 22
})
var testVariable = 12
console.log(window.testVariable) // result: 12
console.log(testVariable) // result: 12
- Why following code runs correctly
<script>
Object.defineProperty(window, 'a', {
value: 33
})
let a = 13
</script>
<script>
console.log(a) // result: 13
</script>
- But the following throws an error.
<script>
Object.defineProperty(window, 'a', {
value: 33
})
</script>
<script>
let a = 13
console.log(a) // Uncaught SyntaxError: Identifier 'a' has already been declared
</script>
When a variable is declared with
varon the top level, as soon as the script tag starts, it's assigned as a writable property of the global object:The same is not true for variables declared with
let- they don't get put onto the global object:When you use
Object.definePropertyto define a property that's already defined on the object, and you pass avalue, like withThe prior value that existed on the object gets overwritten. So with your second code, you're defining a writable property named
testVariableon the global object which then gets overwritten, and bothtestVariableandwindow.testVariableevaluate to12.In contrast, with your first code, top-level variables declared with
letcreate a global identifier, but do not get assigned to properties of the global object, soand
are referring to different things.
This one is quite interesting. According to the specification, when the environment prepares to execute a new
<script>tag, it runsGlobalDeclarationInstantiationto set things up. It does, among other things:Where
envRecis the global Environment Record. (An Environment Record, or Lexical Environment, is a record of which variable names in a given scope refer to which values.)With your code, the section of
GlobalDeclarationInstantiationthat is throwing is this section of 5:In your third code, before the first script tag starts, when
GlobalDeclarationInstantiationruns, the global environment record doesn't have a variable nameda, so no error is thrown. In contrast, in your fourth code, when the second script tag starts, andGlobalDeclarationInstantiationruns, a variable namedadeclared withletalready exists in the global environment record, so theHasLexicalDeclarationcall returnstrue, and an error is thrown. (Variables declared withletcreate lexical declarations; variables declared withvarcreate var declarations.)