A declaration just says that something exists. In JavaScript you can declare variables, functions and (more recently) classes.
In some languages (e.g. C, C++) it's possible to declare something without defining it. For example:
// this declares a function exists with a given signature, but doesn't define its implementation
void someFunction();
someFunction(); // here we call the function, since we know it exists
// here we define the function, which we have to do at some point
void someFunction() { /* ... */ }
This pattern is less common in modern languages, where the declaration and the definition tends to be combined, but it's useful to understand the distinction seeing as your question seems largely about terminology.
Variables can be declared, however they don't have definitions.
let b; // we declare that there's a variable 'b'
Instead you can assign a variable:
b = 5; // assignment
let c = 6; // declaration and assignment in one statement
The concept of binding in computer science has many forms. For example, when you type foo
in your code, binding is the act of working out which variable/function/type/... should be used. In JavaScript this is pretty straightforward, but in some languages it can get pretty hairy (due to things like overload resolution and so forth).
However I don't believe that's what MDN means when they talk about let bindings. I believe it's a shorthand for "let declaration and assignment", as we saw above.
Regardless, I wouldn't worry too much about that term. The most important bit to understand from the paragraph you've quoted is that let
and const
are tighter versions of var
, introduced in recent versions of the language to address pitfalls and surprises that came from the way var
works.
Previously I thought the variable keyword and variable name together comprised a declaration
You're right.
var a;
var b = 1;
let c;
let c = 2;
const d = 3;
These are all declarations of variables (even though const
technical variables can't vary, or more precisely, they cannot be reassigned).
It's just that var
is a bit sloppy and surprising.
You could declare a var more than once within the same scope:
var a = 1;
var a = 2;
This won't work with let
:
let a = 1;
let a = 2; // SyntaxError: Identifier 'a' has already been declared
Scoping on var
can be surprising too:
for (var i = 0; i < 10; i++)
{
var inner = 1;
}
console.log(inner); // prints 1 even though you might think this would be an error
Or worse:
for (var i = 0; i < 10; i++)
{
for (var i = 0; i < 10; i++)
{
console.log('hello');
}
}
At a glance you might think this would print hello
100 times (10*10), but actually it is only printed 10 times because both loops use the same variable. This is a type of programmer error that the language should really prevent. If that code used let i
instead, it would produce a syntax error.
As for hoisting you can think of it as though all the var
declarations were moved to the top of the containing function.
function foo()
{
doThing();
var i = 0;
doSomethingElse();
for (var j = 0; j < 10; j++)
{
var k = 10;
}
}
Even though that's how you might write the code, it behaves as though you had written:
function foo()
{
var i; // all declarations hoisted to top of containing function scope
var j;
var k;
doThing();
i = 0;
doSomethingElse();
for (j = 0; j < 10; j++)
{
k = 10;
}
}
This is why you can write:
i = 10;
var i;
The var
is moved up in the code, so it behaves as:
var i;
i = 10;
You can think of let
as not being moved. Therefore it is an error to reference it before it is declared.