user10108817
user10108817

Reputation: 285

javascript: scoping with let vs none

I have a forEach loop and a for loop nested inside of it. Why is that outside of the for loop , but still inside the forEach loop, I have word = foo. Then that value of word can be logged outside of the entire forEach loop however, when I make it let word = "foo" , the console log statement fails and says word is not defined?

function mainFunction() {
    array.forEach(function (element, index) {
       for (var key in list) {
         //do something
       }
       word = "foo"
    }

    console.log(word)
}

Upvotes: 2

Views: 264

Answers (4)

Mojtaba Nava
Mojtaba Nava

Reputation: 878

function mainFunction() {
array.forEach(function (element, index) {
   for (var key in list) {
     //do something
   }
   let word = "foo"
   //word is defined here.
   //word can call in {array.forEarch(...)}

}
//word is undefined here.

console.log(word)

}

Always let called in {...}. For example: { let a; ... {let b;} {let c;} }

Upvotes: 0

colxi
colxi

Reputation: 8670

Let satement

The let statement declares a block scope local variable, optionally initializing it to a value.

function test(){
  let x = 1;

  if(x === 1) {
    let x = 2;
    console.log(x);// output: 2
  }
  console.log(x); //output: 1
}

test();

console.log(x); // Uncaught ReferenceError

No statement

Variables should be declared with let, const, or var. Omitting them is widely considered a mistake, because the variable ends in the global scope, generating global scope pollution, and difficulty to trace or debug.

It may also incur in variables overriding ( bugs, unexpected behavior...)

If your code runs in "strict mode" (or inside a module), an error will be triggered.

function test(){
  x = 1; // becomes window.x

  if(x === 1) {
    let x = 2;
    console.log(x);// output: 2
  }
  console.log(x); //output: 1
}

test();

console.log(x); // output: 1
console.log(window.x); // output: 1


Solution to your problem

You should declare the variable at the top of your function.

function mainFunction(array) {
    let word; // declare 'word' here
    array.forEach(function (element, index) {
       word = "foo";
    })
    console.log(word)
}

mainFunction([1,2,3,4])

Upvotes: 2

Akrion
Akrion

Reputation: 18515

There are only two scopes in javascript: Global and local. The only thing that can create a scope is the function keyword.

Variables are fetched by first looking into the local scope and if not found are then searched in the parent scope above the chain until found. If not found and use strict mode is not set, they are auto created for you in the global scope.

With that said you can see that what would happen is that the variable word would simply not be found in the scope of forEach. In this case JS does what many people do not want it to do and the reason why many people use use strict mode ... it would add it for you in the global scope since it was not able to located in anywhere in the scope chain.

This causes many issues overall and it is not the behavior many people want. To stop that you can add use strict for tell JS to be in strict mode

'use strict';
var v = "Hi! I'm a strict mode script!"; // this is ok
b = 1 // ReferenceError: b is not defined"

Here is the same without use strict

var v = "Hi! I'm a NOT strict mode script!"; // this is ok
b = 1 
console.log(b) // returns 1

Upvotes: 0

JDB
JDB

Reputation: 25835

If you don't use let, var or const to define your variable, then JavaScript implicitly adds your word variable to the global object.

Basically, this:

word = "foo"

Is the same as this:

window.word = "foo"

This is widely considered to be bad practice and is generally indicative of a mistake. This is why most linters will mark this as an error.

Upvotes: 5

Related Questions