By Ran Bar-Zik | 12/28/2017 | General |Beginners

ECMAScript 6 - Separate scope of each block with let

ECMAScript 6 - Separate scope of each block with let

In the previous article we learned about constants, and in this article we’ll talk about one of the main features of ECMAScript 6—defining a variable with let.

 

In order to understand this feature’s importance, let’s first talk a bit about scope. I’ll assume you know about scope, even if it’s only subconsciously, since it’s one of JavaScript’s most prominent features. But for the sake of review, let’s look at a little code:

 

"use strict";
var x = 5;

function moshe () {
 var x = 123;
 console.log(x); //Will be 123
}

console.log(x); //Will be 5
moshe();
console.log(x); //Will be 5

If we run this code (which you’re welcome to copy & paste into your console), we can see the following in the console:

5
123
5

So what’s going on here? The function moshe has its own scope in which the variable x is completely separate from the global variable x. When we define a variable with var inside of a function, we create a private variable in the scope with which we can work. But this variable is not relevant to “the outside word” aka the code outside of the function. 

 

So what’s the problem?  We want to be able to to define a scope solely to functions and not to other code blocks, for example conditional statements.

 

Let’s define x with the following code:

"use strict";

var x = 5;

if (true) {
 var x = 123;
 console.log(x); //Will be 123
}

console.log(x); //Will be 123

What’s happening here? We define a variable inside the if statement, which should have its own scope. But this doesn’t exit in ECMAScript 5. We can’t define our own scope when ever we want, but rather only inside of a function.

 

So exactly for this we have ECMAScript 6 and let, which allows us to define scope wherever we want—even inside a conditional statement.

 

"use strict";

var x = 5;

if (true) {
 let x = 123;
 console.log(x); //Will be 123
}

console.log(x); //Will be 5

You can run this in the console or open it in codepen and check the console there:

 

In order to demonstrate the issue, I’ll use something that I really like to use on tests—the problem of scope that arises when we try to assign events to objects. Let’s say we have a page with a few buttons on it and we want to print out to the console the button number each time we click on one of them. To do this we’ll use the following code:

 

var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
 buttons[i].addEventListener('click', function() {
   console.log('You clicked button #' + i);
 });
}

Hold on now, don’t freak out! This code is actually pretty simple. What is does is use a JS query in order to put in all of the DOM elements, which are the button on in the buttons array. Using a simple for loop in assign a click event to each button which prints its number to the console.

 

So what’s the problem? Veteran JavaScript coders should have caught it right away. But for the less experienced, check out this codepen:

With each click of a button, we’ll see in the console “You clicked button #3” no matter which button we clicked on. But hold on, what’s going on here? Why don’t we see the number of the button we pressed? This is precisely due to the scope problem! Outside of addEvent the variable i is constant, but inside the assignment of the event i is treated as a global variable. It’s a bit hard to grasp intuitively but every JS developer with enough experience has encountered this problem.

 

There are a few ways to deal with this problem, none of which are any good. One for example:

 

var buttons = document.getElementsByTagName('button');
 
for (var i = 0; i < buttons.length; i++) {
 bindEvent(i);
}
 
function bindEvent(k) {
 var button = buttons[k]
 button.addEventListener('click', function() {
   console.log(k);
 });
}

 

What’s happening here is we’re forcing the JS to create a new scope by defining a function. Then the i that we use is local instead of global. It’s OK if you know the solution, but too complicated if you don’t understand scope completely or are in an intense job interview, or working against a deadline.

 

Once we have an understanding of how scope works in ECMAScript 6 the solution is simple. Using let we implement the new scope quite easily, without using begin forced to use artificial functions to do so.

 

var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
 let j = i;
 buttons[j].addEventListener('click', function() {
   console.log('You clicked button #' + j);
 });
}

You’re welcome to test out the solution here:

 

So what do I recommend you ask? Start using this. It’s no surprise that each time we see a JS variable defined, more and more programmers are using let in order to prevent scope confusion. In fact there are more than a few recommendations to give up on using var altogether.

Previous article: Using Constants in ECMAScript 6

Next Article: Promises in ECMAScript 6

 

About the author: Ran Bar-Zik is an experienced web developer whose personal blog, Internet Israel, features articles and guides on Node.js, MongoDB, Git, SASS, jQuery, HTML 5, MySQL, and more. Translation of the original article by Aaron Raizen.

By Ran Bar-Zik | 12/28/2017 | General

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now