Understanding Javascript: Variables (var, let & const)
Variable
A variable can be described as the identifier of a value, this can be constant so it never changes like PI (3.1415…), or a changing value like the birthdate, it will change depending on the person but you always know what someone is referring to when they say “birthdate”.
The value of a variable can be a primitive or a reference to an object.
In javascript a variable name, also known as identifier, must follow the next rules. First it has to start with a letter (it can be uppercase or lowercase, javascript is case sensitive so hello_world is different than Hello_world), an underscore (_hello), or a dollar sign ($hello), while the next characters can include letters, underscore, digits (0–9) and the majority of the Unicode characters.
Scope
Scope refers to all places where a variable can be accessed, when a variable is available in every place of your code it is called global scope, they normally are variables outside of functions, but when a variable can be accessed only inside a function it is called local scope. There is also something called block scope, where the variable is local and is only available inside a block, a block is considered anything between two braces {}.
In the next code we can see that the value of “y” outside of the function shows an error because its scope is local to the function, this limits it to only be available inside localScope, and “x” having been declared outside the function makes it a global variable.
var x = 1;
function localScope() {
var y = 2;
console.log(y); // 2
}
localScope();
console.log(x); // 1
console.log(y); // Uncaught ReferenceError: y is not defined
Javascript has three different ways of declaring variables which are var, let and const, lets see each of them:
VAR
This way declares a variable which can be optionally initialized with a value, this means you can write var x
or var x = 1
, and its value can change during the execution of your program. In the next code i show you how the value of x changes using console.log. Use your favorite editor and change the values assigned to x, you will see how the values in your console change correspondingly.
var x = 1;
if (x === 1) {
var x = 2;
console.log(x); // expected output: 2
}
console.log(x); // expected output: 2
When var is created during hoisting, which is the process javascript uses before executing the code to create the space in memory for the variable, a value of undefined is assigned to it indicating it doesn’t has a value assigned yet or it hasn’t been declared, this will change once the code is executed and its first assignation is made. If a value is never assigned like declaring var x
but never assigning x = 'something'
, then the value will always be undefined.
'use strict';
console.log(x); // undefined (note: not ReferenceError) due to hoisting
var x = 1; // assigns a value
console.log(x); // 1
Now lets talk about its scope, var is only limited by functions and modules, in case of not being inside any of them then it has a global scope.
'use strict';
function foo() {
var x = 1;
function bar() {
var y = 2;
console.log(x); // 1 (function `bar` closes over `x`)
console.log(y); // 2 (`y` is in scope)
}
bar();
console.log(x); // 1 (`x` is in scope)
console.log(y); // ReferenceError in strict mode, `y` is scoped to `bar`
}
foo();
Variables declared with var can be duplicated without getting an error, even using ‘strict mode’, javascript will recognize it as if it was a new assignation. In big blocks of code this could cause some errors, this is why the javascript community heavily recommends using let instead.
var x = 2;
console.log(x) // 2
var x = 3;
console.log(x) // 3 (no error showed)
LET
This way of declaration can be optionally initialized like var but it has block scope, this means it can only exists inside a block or expression it was declared unlike var which can exist globally or locally, but similar to var its value can change during the execution.
In the next example we can see how javascript will not see as if we were repeating “x” using let, but it will appear as a new variable that only exists inside that block, therefore let x = 1
does not exists here since it was replaced by let x = 2
.
function varTest() {
var x = 1;
{
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
{
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}
varTest();
letTest();
Similar to var, let gets also initialized with undefined during hoisting, but different than this one let cannot create properties inside the global object or window when it is declared globally.
var x;
let y;
console.log(x); // undefined
console.log(y); // undefined
x = 'global';
y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
CONST
This one has a block scope just like let, it is constant hence its value can’t change nor be declared again and it always has to be initialized.
const FOO; // Uncaught SyntaxError: Missing initializer in const declaration
const number = 42;
try {
number = 99;
} catch (err) {
console.log(err);
// expected output: TypeError: invalid assignment to const `number'
// Note - error messages will vary depending on browser
}
console.log(number); // expected output: 42
Although it cannot be reassigned, const has the behavior that if you assigned an array or an object, you can change its properties.
const objectExample = { a: 3, b: 2, c: 1};
console.log(objectExample); // { a: 3, b: 2, c: 1}
objectExample.b = 3;
console.log(objectExample); // { a: 3, b:3, c: 1}
objectExample = { other: 'value' };
// Uncaught TypeError: Assignment to constant variable.
const arrayExample = [];
arrayExample.push('a'); // ["a"]
arrayExample = ['b']; // Uncaught TypeError: Assignment to constant variable.
Considering that const only exists inside a block, this cannot be declared alone inside one because there will be no way of accessing it outside of the block.
if (true) const a = 1; // SyntaxError: Unexpected token 'const'
Other ways of declaring variables
Sometimes you will find variables declared in a different way than the ones seen above, so lets talk about them.
Destructuring
It helps you get a specific property from an object or array and assign it to a new variable. See the next example:
const foo = { bar:10, baz:12 }
const { bar } = foo;
console.log(bar); // 10
const gg = ['23', 34];
const [ num1, num2 ] = gg;
console.log(num2); // 34
We can also use let or var so we can change the value of the new variable without modifying the original object.
const foo = { bar:10, baz:12 }
let { bar } = foo;
console.log(bar); // 10
bar = 35;
console.log(foo); // { bar: 10, baz: 12 }
console.log(bar); // 35
Undeclared or implicit variables
To understand this types of variables we have to understand how the global scope works. When you create a variable with global scope this gets added to the global object and it cannot be changed or deleted and it has the advantage of using it everywhere without the necessity of calling globalThis., window. or global.
If you wanted to declared a global variable you could do this:
foo = 'f' // In non-strict mode
Object.hasOwn(globalThis, 'foo') // true
This changed with ECMAScript 5, this kind of assignation using strict mode will show a ReferenceError, this was made to avoid the creation of properties inside the global object by mistake. Therefore JavaScript does not have implicit or undeclared variables, it merely has a syntax that adds to the global object.