- ES6 common features (Part 1);
- ES6 common features (Part 2);
- ES6 common features (Chapter 3);
- ES6 common features (latest);
ECMAScript overview
ECMAScript is also a scripting language, commonly abbreviated as ES, and is often thought of as the standard specification for JavaScript.
But JavaScript is actually an extension of ECMAScript, because ECMAScript only provides the most basic syntax. In general, ECMAScript only dictates how code should be written, such as how we should define variables or functions, and how we should implement branching or looping statements. This is just at the language level. It doesn’t accomplish the actual functionality of our application.
JavaScript implements standard development, and makes certain extensions on the basis of this language, making it possible to operate DOM and BOM in the browser environment. The Node environment allows you to do things like read and write files.
So basically, JavaScript in the browser environment is ECMAScript plus the API provided by the Web, which is what we call DOM and BOM.
Js itself stands for ECMAScript + DOM + BOM;
The JavaScript used in the Node environment is essentially ECMAScript plus a set of apis provided by Node. Such as the apis provided by built-in modules such as FS or NET.
So the language itself in JavaScript refers to ECMAScript, and with the development of the web application model over the years, ECMAScript has maintained a large version of the iteration every year since 2015. With the iteration of these new versions, many new features have been introduced, which has resulted in the JavaScript language itself becoming more and more advanced and convenient.
There are a lot of things worth knowing about ES2015 alone, because it is relatively special in this release, and it took nearly 6 years for it to be fully standardized after the last release of ES5. And those six years were a golden time for the Web.
Therefore, this version contains a lot of subversive new functions. It is precisely because of the long time of ES2015 iteration that too much content is released, so the release conference of ES becomes more frequent from the later version, which is more in line with our current spirit of small steps and fast running of the Internet. And since ES2015 ECMAScript has decided not to name itself by version number, but by release year.
Since such a decision was made during the birth of ES2015, many people were already used to the name ES6, so some people called it ES6 for ES2015.
As ECMAScript continues to iterate steadily, the mainstream operating environments on the market are following suit and supporting the latest features, so it’s important for us as JavaScript developers to learn these new features.
Let’s take a look at some of the core and most useful new features released in ES2015.
ES2015 overview
ECMAScript2015 can also be called ES6, which is a representative version of the new ECMAScript standard. On the one hand, it has changed a lot compared to the last version, and on the other hand, its naming rules have changed since this version, and the more accurate abbreviation is called ES2015.
By the way, there are a lot of developers who use the name ES6 to refer to all new releases from ES5.1 onwards. For example, we see async and await using ES6 in many references. But actually async and await are the standards specified in ES2017. So in the future, we need to pay attention to distinguish between the ECMAScript2015 standard and all new standards.
The ECMAScript2015 standard specification is 26 chapters long. If you can take a moment to briefly review the full ES2015 language specification, it does not just cover the new features introduced in this release, but all the language standards since the new features.
Here are just some of the important new features in the ES2015 standard that are worth looking at separately. These changes are grouped into four simple categories.
The first is to address some of the problems or shortcomings of the original syntax, such as block-level scopes provided by lets or const.
The second category is to enhance the original syntax to make it more convenient and easy to use, such as deconstruction, expansion, parameter defaults, template strings and so on.
The third category is new objects with new methods and new functionality, such as Promise and Proxy, and methods like Object.assign.
The fourth category is new data types and data structures, such as Symbol, Set, Map, etc.
Let’s take a look at some of the major new features.
Let and block-level scope
Scope, as the name implies, is the scope within which a member of our code can act.
Before ES2015, ECMAScript had only two types of scope: global scope and function scope. A new block-level scope has been added in ES2015.
A block is the scope of our code wrapped in a pair of {}, such as the {} in the if and for statements that produce the block.
if (true) {
console.log('yd');
}
for (var i = 0; i < 10; i++) {
console.log('yd');
}
Copy the code
Previously, blocks had no separate scope, which led to access outside the members we defined in the block. For example, if we define a variable foo in if, and then print foo outside of if, the result will print normally.
if (true) {
var foo = 'yd';
}
console.log(foo); // yd
Copy the code
This is not safe for complex code. With block-level scope, we can declare variables in code with a new keyword, let.
It is used in the same way as traditional var, except that variables declared by let can only be accessed in the declared code block. Let’s change the var attempt we just made to let and save it.
if (true) {
let foo = 'yd';
}
console.log(foo); // yd
Copy the code
The console will print an error saying foo is not defined, which means that members defined within the fast level are not externally accessible.
Such a feature is ideal for declaring counters in a for loop. Traditional for loops require different names for counters if they are nested. Otherwise there will be problems.
Let’s say we have two for loops nested here, and we have two for loops nested with counters called I, and then we print the I in memory.
It should print 9 times, but after we execute it, we find that there is a problem here. It only prints 3 times.
for (var i = 0; i < 3; i++) {
for (var i = 0; i < 3; i++) {
console.log(i); }}Copy the code
The loop declares I again after the outer layer declares I, and they are all declared using var, that is, not a fast scoped member, but a global member.
So the I declared by the inner layer overwrites the I declared by the outer layer, and by the time the loop completes, our I is going to be 3, and for the outer layer, the I that the outer layer gets is still the global I which is 3. It does not satisfy the cycle conditions, and it will not continue to cycle.
This would not be a problem if we were using let, because a variable declared by let can only be used in the current loop block.
Here we change var to let, and the inner loop will normally execute 9 times.
for (let i = 0; i < 3; i++) {
for (let i = 0; i < 3; i++) {
console.log(i); }}Copy the code
Since the I in the memory loop is a local member of the inner fast scope, it is important to note that it is the let in the inner loop that really solves the problem here, since it is the let that keeps our inner I in a box and no longer affects the outside.
We can even change the external let back to var.
Although the let keyword solves the problem caused by our counters having the same name in the loop nesting, it is generally not recommended to use counters with the same name, as this is not good for later understanding of our code.
In addition, a typical application scenario is that when we register an event in a loop, in the event handler, we need to access the counter in the loop, and in this case, some problems have occurred in the past.
To demonstrate this, we define a Elements array, in which we define three member objects, each an empty object that represents an interface element.
We then iterate through the array and simulate adding an onclick event to each element, essentially adding an onclick method. And then in the event handler we’re going to access the current loop counter, which is I and we’re going to print it out.
Once we’re done, we’ll go to the end of the loop and then we’ll call onclick on any of the elements.
var elements = [{}, {}, {}];
for (var i = 0; i < elements.length; i++) {
elements[i].onclick = function() {
console.log(i);
}
}
elements[0].onclick();
Copy the code
You’ll notice that the I printed here is always 3. This is because the I we printed here is actually always the I in the global scope. After the loop completes, our I has been accumulated to 3, so the result is the same no matter which element we print click.
This is also a typical application scenario for closures, a problem that can be solved by creating closures.
var elements = [{}, {}, {}];
for (var i = 0; i < elements.length; i++) {
elements[i].onclick = (function(i){
return function() {
console.log(i);
}
})(i)
}
elements[0].onclick();
Copy the code
In fact, closures are also using function scope to get rid of the influence of global scope. Now that we have block-level scope, we don’t need to bother. We just need to change the var that declares counters to let
Using the new keyword let or const declaration, as distinct from var, makes I accessible only in the block-level scope, which naturally solves our problem.
var elements = [{}, {}, {}];
for (let i = 0; i < elements.length; i++) {
elements[i].onclick = function() {
console.log(i);
}
}
elements[0].onclick();
Copy the code
In fact, it is also a closure mechanism, because by the time we execute onclick, the loop will have ended and the actual I will have been destroyed. It is because of the closure mechanism that we can get the value of the I that was used to execute the loop.
There’s also something special about the for loop, because inside the for loop it actually has two levels of scope, so let’s add a for loop here that uses let to declare I =’foo’, and then inside the for loop we declare let to declare I =’foo’, and you might think that the two I’s clash.
for (let i = 0; i < 3; i++) {
let i = 'foo';
console.log(i);
}
Copy the code
At this point, foo is normally printed three times in the console, which means that our two I’s are actually independent of each other. That is, they are not in the same scope.
This might be a little confusing, but let’s just break this up and do it in if form, and we can see that the for loop is actually executing let I = 0; And then I < 3; If it’s less than 3, continue, declare I =foo in if, and then I ++ after if is done; And so on, that’s the whole cycle.
let i = 0;
if ( i < 3) {
let i = 'foo';
console.log(i);
}
i++;
Copy the code
Now you can see that let I = foo is actually a local variable inside a block-level scope like if, and the outer loop counter is actually a local variable generated inside this block of the outer loop. So they don’t influence each other.
Then you can understand why there are two nested scopes: the I in the body of the loop is the memory-independent scope, and the outer scope is the for loop itself.
In addition to the quick scope limitation, a big difference between a LET and a VAR is that the let declaration does not improve.
The traditional var method of declaring a variable causes the variable we declared to be raised to where we started our code. For example, we declare a foo with var, and then we print the foo before we declare it.
console.log(foo);
var foo = 'yd';
Copy the code
Instead of an error, our console will print undefined, which means that foo was already there when we printed it, just not yet assigned, a phenomenon called raising variable declarations.
In fact, at present, such a phenomenon is actually a bug, but we joke that the official bug is not called a bug, should be called a feature.
To correct such a problem, ES2015’s let removes such a so-called feature. He asks us syntactically to declare variables before we use them. Otherwise, an undefined error is reported.
We can change this var to let and save it to see an error in the console that references an exception.
These are some of the most important features of let and block-level scopes. As for why ES2015 did not make some upgrades on the basis of the original VAR but defined some new keywords.
For the simple reason that upgrading var directly would have caused many previous projects to fail, ECMAScript decided to use a new keyword called let.
const
ES2015 also added a const keyword, which can be used to declare a read-only constant or constant. This feature is based on the let feature.
Read-only means that a variable cannot be modified once it has been declared. For example, we can declare a name by const and its value is YD. If we modify the member after the declaration, an error will occur.
const name = 'yd';
name = 'zd';
Copy the code
Since const is constant, that means that const must set an initial value at the same time it is declared. Declarations and assignments cannot be put in two statements like var.
// const name = 'yd';
var name2;
name2 = 'yd';
Copy the code
One more thing to note here is that const members declared cannot be modified, only that we are not allowed to refer to a new memory address after being declared. This is not to say that attribute members in a constant are not allowed to be modified.
For example, if we define a const obj equal to an empty {} and then set the object’s name property, it doesn’t actually change the memory address that obj points to. He just modifies the data in this memory space. So it’s allowed.
const obj = {}
obj.name = 'yd';
Copy the code
But it is not allowed to say that we are equating obj to a new empty object. Because assignment changes the memory orientation of OBj.
Other features are the same as the let keyword, so we don’t need to demonstrate them separately.
So far we have seen the two new keywords in ES2015, let and const, together with the original var, there are three keywords that can be used to declare variables.
We generally don’t use var, mostly const, and let for variable changes. Choosing in this way can actually improve the quality of your code significantly. The reason for this is simply that some of the features of VAR are bad development practices. For example, to use variables first and then to declare variables, this is a bad habit, so we resolutely do not.
The reason we use const by default is because it allows me to make sure that the members declared in our code are not being modified.
Array deconstruction
ECMAScript2015 adds a shortcut to get specified elements from arrays or objects. This new syntax is called deconstruction.
So let’s say we have an array, and we have three different values in the array, and we used to need to get the elements in the array and we needed to access the values through the index. The result is then placed in a variable.
const arr = [100.200.300];
const foo = arr[0];
const bar = arr[1];
const baz = arr[2];
console.log(foo, bar, baz);
Copy the code
Now we can use the method of deconstruction to quickly extract the specified member in the array. The specific use is to change the place where we defined the variable name to an array [], which is the variable name of the data we need to extract. Internally it allocates the value of the position in the array according to where the variable name appears.
const arr = [100.200.300];
// const foo = arr[0];
// const bar = arr[1];
// const baz = arr[2];
const [foo, bar, baz] = arr;
console.log(foo, bar, baz);
Copy the code
If you just want to get the member corresponding to one of the locations, for example, just the third member, you can delete the first two members here. But keep the corresponding comma. Make sure the format of the deconstruction location is consistent with our array. That way you can extract the member at the specified location.
const [, , baz] = arr;
console.log(baz);
Copy the code
We can also add three variables before the name of the deconstructed location. Retrieves all members from the current position, and all results are placed in an array.
const [foo, ...rest] = arr;
console.log(rest);
Copy the code
Note that this three-point usage can only be used on the last member of the deconstruction position, as in this case to an array of 200 and 300 members.
In addition, if the number of members in the deconstructed location is less than the length of the array to be deconstructed, it will be extracted in the order from front to back, and the extra members will not be extracted.
Conversely, if the member of the deconstructed location is larger than the length of the array, the extracted value is undefined. This is the same as accessing a nonexistent index in an array.
const [foo, bar, baz, more] = arr;
console.log(more); // undefined
Copy the code
If we need to set the default value for the extracted member, this syntax is also supported. We just need to write an equal sign after the deconstructed variable, and then write a default value after it, so that if we do not extract the corresponding member from the array, the variable will be the default value here.
const [foo, bar, baz, more = 'default value'] = arr;
console.log(more);
Copy the code
Above is an array of deconstruction some basic usage, this new syntax in many scenarios will bring us a lot of convenient, we went to split a string, for example, then the specified location, after get the traditional approach is to need a temporary variable to do in the middle of the transition, through deconstruction can be such a process is greatly simplified. Make it easier.
Object deconstruction
In ECMAScript2015, in addition to arrays, objects can also be deconstructed, but the object structure needs to be extracted according to the property name, not the location.
Because the elements in the array have subscripts, that is to say, he has order rules, and the members of the object does not have a fixed order, so it can not be extracted according to the position.
For example, let’s define an obj object.
const obj = { name: 'yd'.age: 18 };
Copy the code
{} is also the name of the variable stored in the extracted data, but the variable name here also has an important role is to match the members of the deconstructed object, so as to extract the value of the specified member. For example, the name used here.
const obj = { name: 'yd'.age: 18 };
const { name } = obj;
Copy the code
This is taking the property value of the OBj object and putting it in the name variable.
Other features of deconstructing objects are basically identical to those of deconstructing arrays. Unmatched members return undefined, or the default value can be set.
In a special case of objects, the name of the deconstructed variable is the name of the property of the object being deconstructed, so there is a conflict if the name is present in the current scope. At this point we can use the rename method to solve the problem.
const obj = { name: 'yd'.age: 18 };
const { name: name1 } = obj;
console.log(name1);
Copy the code
There are a lot of scenarios for deconstructing objects, but most of them are intended to simplify our code. For example, if the console object method is heavily used in the code, we can first deconstruct the object separately and then use a separate log method.
const { log } = console;
log('1');
Copy the code
Template string
ECMAScript2015 also enhances the way strings are defined. Traditionally, strings are identified by single or double quotation marks, and strings are identified by single or double quotation marks. ES2015 has added template strings, declared with back quotes. If you need to use backquotes in a string, you can use a slash to translate it.
This template string approach has some very useful new features over regular strings.
First of all, the first thing is that traditional strings don’t support line breaks. If we have a line break in the contents of a string, we need to represent it with a \n character.
The latest template strings support multi-line strings. That is, we can enter a newline character directly into the string.
const str = 123 456 ` `
Copy the code
This is very handy for us to output HTML strings.
Secondly, the template string also supports interpolation to embed the corresponding value in the string, for example, we define a name variable, and then we can use ${name} in the string to embed the value of the name variable in our string.
const name = 'yd';
const age = 18;
const str = `my name is ${name}, I am ${age} years old`;
Copy the code
It’s a little bit more intuitive than the multiple pages of string concatenation. In fact, the contents of ${} are standard JavaScript, which means that you can embed not only variables, but also any standard JS statement.
The return value of this statement will eventually be printed to the position in our string where the interpolation exists.
Tagged template string
A more advanced use of template strings is that they can be defined with a tag in front of them, which is actually a special function. Adding the tag calls the function.
We define a name and gender variables first, and then a template string that uses the tag function.
const name = 'yd';
const age = 18;
const result = tag`My name is ${name}, I am ${age} years old`;
Copy the code
To use this tag function, we need to define the tag function first. We define a tag function, and this function can receive an array parameter, which is the result of our template string content split. This is because there may be embedded expressions in the template string, so the array is essentially the static content of the expression split. So it’s an array.
const tag = (params) = > {
console.log(params); // ['My name is ', ' I am ', ' years old'];
}
Copy the code
In addition to this array, this function can also receive the return value of any expression that appears in our template string. For example, our template string uses the difference of name and age, so we can receive the corresponding value of name and age here.
const tag = (params, name, age) = > {
console.log(params, name, age); // ['My name is ', ' I am ', ' years old']; 'yd' 18
}
const str = tag`hello The ${'world'}`;
Copy the code
The internal return value of this function will be the value of our tagged template string. For example, if we return ‘123’ in this function, our result will be ‘123’;
const tag = (params, name, age) = > {
return '123';
}
console.log(result); / / '123';
Copy the code
So if we want to return the normal content, this should be a concatenated string, and that will give him back the result of our template string concatenation.
const tag = (params, name, age) = > {
return params[0] + name + params[1] + age + params[2];
}
Copy the code
The function of this tag function is actually to process our template string, such as age, which directly outputs 18. We can process it in the function to make it more readable by the user.
You can take advantage of such a feature of tags to implement multilingualization of text, such as translating it into Chinese or English, or checking for unsafe characters in template strings.
Settings you can also use this feature to implement a small magic board engine is also available.
String extension method
ECMAScript2015 provides a number of extension methods for string objects. Here’s a look at some of the most common ones. Includes, startsWith, and endsWith are a set of methods that make it easier to determine if our string contains the specified content.
For example, let’s define a string called MASSAGE, and the content of the string is an error message. Assume that this is an error message received while the program is running.
const message = 'ErrorL foo is not defined.';
Copy the code
If we want to know if the string startsWith Error, we can use startsWith to find out, passing in what we need to find through message.startswith. The result is true.
console.log(message.startsWith('Error')); // true
Copy the code
Similarly, if we want to know if this string is. At the end, we can use endsWith. The result is also true.
console.log(message.endsWith('. ')); // true
Copy the code
If we need to make sure that the middle of the string contains something, such as foo, then we can use the includes method, which also results in true.
console.log(message.includes('foo')); // true
Copy the code
This set of methods will make searching for strings much easier than using indexOf or the regular method before.
Welcome to pay attention, more content continues to update