ES6 - A beginners guide - New Variable scoping (Let and Const)
source link: https://dev.to/stefanwrightcodes/es6-a-beginners-guide-new-variable-scoping-let-and-const-3jpe
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Hello again!
Welcome back! It's great to see you on this entry in the series. This time we are going to discuss the new variable scopes called let
and const
. In ES6 we can essentially forget about var
and just use our new friends let
and const
to have much more control over our variables, ensure that they contain the exact data that we expect at the very point in our code execution.
So what are they?
Although less commonly used now with the introduction of ES6 we'll include var
in the explanations below.
var
var
can be seen as the most relaxed kind of declaration, it is left open for redeclaration, and also redefinition. For example:
var a = 1; // window.a = 1
var a = 2; // window.a = 2
var b = 1; // window.b = 1
b = 2; // window.b = 2
Neither of these will cause the browser to throw an error or exception. Let's have a look at another var
example which you may come across:
var a = 1;
function logVariable() {
console.log(a);
var a = 2;
}
logVariable(); // Returns undefined in a console log
console.log(a); // Returns 1 in a console.log
Wait...what? How can we reference a before declaring it? This is what is known as Hoisting. Hoisting is where the JavaScript engine processes the var delcarations during compilation time but it does not assign it a value until the expression is executed so until that time you receive undefined as the return value.
Also, notice how the final console.log returns 1? This is because the first var is globally scoped, and the second is function scoped. So even though in the function we set a = 2, that was in the function scope and would only output 2 if we set a console.log after the assignment in the functions. As we had already set a = 1 at the global scope level when we console.log that outside the function it will use the global var
.
So, what about let
?
let
is block scoped and so applies to everything inside
let a = 1;
console.log(a); // Returns 1 in a console.log
const logVariable = () => {
console.log(a); // Uncaught ReferenceError
let a = 2;
};
logVariable(); // Throws an exception
console.log(a); // Doesn't run because of the exception
If you try to run the JavaScript above you will find that it throws an Uncaught ReferenceError, this is because whilst let
's are hoisted but not initialized, they live in a "Temporal Dead Zone" (TDZ) meaning we cannot actually access it, thus throwing the ReferenceError.
Patricia has some great descriptions of Hoisting and the TDZ in her article here:
When we hit an exception like we see in the above example it stops the rest of the JavaScript in that block from functioning and thus we do not see the final console.log().
It is worth noting that let
's can be re-assigned but not re-declared, for example if we re-assign the variable:
let a = 1;
a = 2;
console.log(a); // Returns 2 in a console.log
but if we try to redeclare the variable as we see below, it will throw an exception:
let b = 1;
let b = 2;
console.log(b); // Throws a SyntaxError because b has already been declared
Interestingly, if you run both of the above snippets at the same time, neither console.log's will output anything despite one of them referencing a variable already defined and assigned, this again is because of hoisting. The declarations are hoisted to the top, and the JS engine detects that there are two declarations for b
throws the exception before attempting to execute anything in that block of code.
How about const
?
The introduction of const
is a nice one. It allow's us to add a level of security to our variables knowing they cannot be changed, well the changes are restricted...i'll go into that in a bit though. As with let
, const
's are hoisted and will also land in the TDZ during compilation, they also cannot be redeclared and are not available in the global scope.
A key difference between let
and const
is that const
requires assignment at the point of declaration, you cannot create a const
and then give it a value. Once given a value, that value is constant (almost).
const a; // Uncaught SyntaxError: Missing initializer in const declaration
const b = 1
b = 2 // Uncaught TypeError: Assignment to constant variable.
I mentioned above that changes to a const
are restricted as opposed to flat-out saying they cannot change. Look at the below example, you'll see that I create a const
which is assigned an object (array's behave the same here), I can modify the contents of the object/array but I cannot completely change the assignment of the const itself. Let's get an example using an object:
const obj = {name: "Stefan"};
obj = {}; // Uncaught TypeError: Assignment to constant variable.
obj.name = "Bob";
console.log(obj) // Returns Bob in a console.log
and an example using an array:
const arr = [1, 2, 3];
arr = [] // Uncaught TypeError: Assignment to constant variable.
arr.push(4) // You can push into a const array
arr[0] = 11 // You can also modify at the point of an array
console.log(arr) // Returns [11, 2, 3, 4] in a console.log
Why??
Ultimately, const
is a "Constant Reference" as opposed to a "Constant Value", this is because the declaration and assignment of a const is to a point in memory. Depending on the data type depends if the reference value is mutable or not. When you assign a string, boolen, number, or maybe even a function you are assigning a primitive value. When you assign an Object or an Array these are non-primitive. The assignment will be protected and y but the data inside it will not be protected. Primitive values are immutable whereas Objects and Arrays are mutable (can be changed). If you are using a const with an Object, and you want to lock those values in, you can use Object.freeze() to do this, see this example:
const obj = Object.freeze({name: "Stefan"});
obj.name = "Bob";
// If you are setting 'use strict' in your code then you will see
// Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'
// Else it will silently fail
console.log(obj) // Returns Stefan in a console.log
Recommend
-
141
Srebalaji Thirumalai ...
-
44
变量 var存在的问题 可以重复声明 无法限制修改 没有块级作用域 (在全局范围内有效) 存在变量提升 const/let 不可以重复声明
-
13
Everything I Wish I Knew About JavaScript Scoping A Week Ago (The Video) Check out my youtube vid going into the second half of my post of the same name (yes I am aware by only capturing half of the written post the title is...
-
9
Everything I Wish I Knew About Javascript Scoping A Week Ago The second half of this blog post now lives in video form here About a week ago I began a deep dive into th...
-
9
I was considering using environment variables to do some simple configuration management. To this end I experimented with ways to set environment variables and access them in a (Python) program. In the following I list some basic obse...
-
7
“I’ve been mad for fucking years, absolutely years, been over the edge for yonks, been working me buns off for bands…” “I’ve always been mad, I know I’ve been mad, like the most of us…very h...
-
11
ES6篇——var、let、const区别 es6主要新增了const和let,...
-
6
Nov 29th, 2017What's New in CSS? Variables, Scoping, New Selectors and Color Functions👇 Download Show
-
9
Contributor rsc commented
-
5
...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK