Skip to content
Muhammet Şafak
tr
Languages 4 min read

Getting Started with ES6: let, const, and Arrow Functions

An introduction to the most impactful ES6 features — let, const, arrow functions, and template literals — with practical examples.


In June, ES6 (ECMAScript 2015) was officially finalized. The ECMAScript specification, which defines the core standard for JavaScript, just received its first major release since ES5 back in 2009. Six years in the making.

Browser support is not yet complete — older browsers in particular have issues. But by using Babel (a transpiler), you can convert ES6 code down to ES5, which means you can write modern JavaScript and still run it in older browsers. In this post I’ll cover the three additions that make the biggest day-to-day difference: let/const, arrow functions, and template literals.

The problem with var, and let/const

For a long time in JavaScript, var was the only way to declare a variable. It has two notable characteristics: it is function-scoped, and it is hoisted. These traits can lead to surprising behavior:

for (var i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i); // Prints 3 every time
    }, 100);
}

Because var i belongs to the surrounding function rather than the loop block, by the time setTimeout fires, i is already 3.

let is block-scoped: it lives only within the {} block where it is declared.

for (let i = 0; i < 3; i++) {
    setTimeout(function() {
        console.log(i); // 0, 1, 2 — the expected behavior
    }, 100);
}

const is also block-scoped, but with one extra constraint: once assigned, it cannot be reassigned. Using it for values that should not change makes the intent of the code explicit.

const API_URL = 'https://api.ornek.com';
// API_URL = 'something else'; // TypeError

const kullanici = { isim: 'Ali' };
kullanici.soyisim = 'Veli'; // Valid — the object's contents can change
// kullanici = {};           // Invalid — you cannot reassign the reference

The important distinction is that const freezes the reference, not the object itself. The object’s properties can still be mutated; what you cannot do is point kullanici at something else entirely.

The rule I use in practice: declare everything with const first, and switch to let only when I genuinely need to reassign. Never go back to var. This habit lets anyone reading the code answer the question “does this value change later?” at a glance.

Arrow Functions

One of the most useful additions in ES6. The syntax is more concise, and this binding works differently.

Old syntax:

var kareler = [1, 2, 3, 4].map(function(sayi) {
    return sayi * sayi;
});

With an arrow function:

const kareler = [1, 2, 3, 4].map(sayi => sayi * sayi);

In the concise form, if there is a single expression, you can omit return and the curly braces. Multiple parameters require parentheses:

const topla = (a, b) => a + b;
const selamla = isim => `Merhaba, ${isim}!`;

On the topic of this binding — arrow functions do not define their own this. They inherit it from the enclosing scope. This solves a very common problem when accessing object properties inside a callback:

function Zamanlayici() {
    this.saniye = 0;

    setInterval(() => {
        this.saniye++; // Correct `this` — the Zamanlayici instance
        console.log(this.saniye);
    }, 1000);
}

With the old approach, you would have written a workaround like var self = this;. Arrow functions make that unnecessary.

That said, arrow functions are not appropriate everywhere. When used as a method on an object, this does not behave as expected — because the arrow function does not bind this; it inherits it from the outer scope. In those cases, a traditional function expression is still the right choice.

Template Literals

String concatenation with + often produced hard-to-read code:

var mesaj = 'Merhaba ' + isim + ', hesabınızda ' + bakiye + ' TL var.';

With ES6 template literals, you embed variables directly inside backtick strings:

const mesaj = `Merhaba ${isim}, hesabınızda ${bakiye} TL var.`;

Multi-line strings are now natural as well:

const html = `
  <div class="kart">
    <h2>${baslik}</h2>
    <p>${aciklama}</p>
  </div>
`;

Previously you would have dealt with a mess of \n and + operators.

The ${} placeholder accepts any JavaScript expression, not just variables — things like ${sayi * 2} or ${kullanici ? kullanici.isim : 'Misafir'}. That flexibility is especially useful when generating dynamic content.

Where to start?

Using ES6 without Babel today is still risky due to inconsistent browser support. But if you have Babel set up with a build step (via Gulp or Webpack), writing ES6 is completely viable. I started using let/const and arrow functions with Babel and it took only a few days to feel natural.

Letting go of old JavaScript habits takes a little time. Start with const, fall back to let when you actually need reassignment — once I committed to that rule, I found myself asking “does this value change?” far less often when reading code.

ES6 is not something you learn all at once. Beginning with let/const and arrow functions, then adding template literals — these three features have an immediate impact on everyday code. The rest — destructuring, spread, modules — comes with time. There is no rush; even just these three features noticeably improve code readability.

Tags: #JavaScript
Share:

Comments

Sign in with your GitHub account to join the discussion. Comments are stored in GitHub Discussions.

Related Posts

Search the site

Start typing to search posts, projects and pages.

Esc to close Powered by Pagefind