Modular
In ES6, modularity becomes a standard feature of JavaScript. ES6 modularity provides a more elegant and maintainable way to organize and manage JavaScript code, which can effectively avoid global variable pollution and naming conflicts. Here are some of the key features of ES6 modularity:
- Export:
export
You can export a variable, function or class to a module through keywords for use in other modules.
For example, the following code exports a function square as a module:
// module.js
export function square(x) {
return x * x;
}
- Import: You can import a variable, function or class from other modules through
import
keywords and use it in the current module.
For example, the following code imports the square function from the module.js module and uses it:
// app.js
import {
square } from './module.js';
console.log(square(5)); // 25
- Default export: A variable, function or class can
export default
be exported as a module by default through syntax.
For example, the following code exports a function add as a module by default:
// module.js
export default function add(x, y) {
return x + y;
}
- Default import: A variable, function or class can
import
be imported by default from other modules through syntax and used in the current module.
For example, the following code imports the add function from the module.js module by default and uses it:
// app.js
import add from './module.js';
console.log(add(2, 3)); // 5
In short, ES6 modularity provides a more flexible and maintainable way to organize and manage JavaScript code, which can effectively avoid global variable pollution and naming conflicts.
Class class
ES6 introduced class
keywords to provide a more concise and object-oriented way to define and use objects. class
It can be regarded as a special function in JavaScript, which can define a class and create instances of the class. Here are class
some of the key features of ES6:
- Class definition: Use
class
keywords to define a class.
For example, the following code defines a class named Person:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${
this.name}, I'm ${
this.age} years old.`);
}
}
- Constructor: Use the constructor method to define the constructor of a class.
For example, the following code defines a constructor for the Person class:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
- Class methods: Use class methods to define methods of a class.
For example, the following code defines a sayHello method of the Person class:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${
this.name}, I'm ${
this.age} years old.`);
}
}
- Class inheritance: Use the extends keyword to implement class inheritance.
For example, the following code defines a Student class, which inherits from the Person class:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${
this.name}, I'm ${
this.age} years old.`);
}
}
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
study() {
console.log(`${
this.name} is studying in grade ${
this.grade}.`);
}
}
- super keyword: Use the super keyword to call the constructor and methods of the parent class.
For example, the following code calls the constructor of the Person class using the super keyword:
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
}
In short, ES6 class
provides a more concise and object-oriented way to define and use objects, which can greatly simplify the writing and maintenance of JavaScript code. At the same time, ES6 class
also supports important features of object-oriented programming such as inheritance and polymorphism, making JavaScript code more flexible and scalable.
Symbol
ES6 introduces a new primitive data type Symbol
, which is an immutable primitive value that can be used as a unique identifier for an object's properties. Each Symbol
value is unique, they will not be repeated. Symbol
Is a data type similar to string, but its value is unique, immutable, and will not be automatically converted to other types.
You can use Symbol()
the function to create a new Symbol
value, which can accept an optional description string as a parameter to describe the Symbol
purpose of the value, but this description string will not Symbol
affect the uniqueness of the value.
Here are Symbol
some features of :
Symbol
The value can be used as the attribute name of the object. Because eachSymbol
value is unique, there will be no naming conflict problem. In object literals,Symbol
properties can be defined using square bracket syntax.
const mySymbol = Symbol();
const obj = {
[mySymbol]: 'value'
};
console.log(obj[mySymbol]); // 输出 'value'
Symbol
Values are not automatically converted to strings and therefore cannot be used as part of object property names, otherwiseTypeError
an error will be thrown.
const mySymbol = Symbol();
const obj = {
};
// 正确做法:将 Symbol 作为属性名
obj[mySymbol] = 'value';
// 错误做法:将 Symbol 转换成字符串作为属性名
obj[mySymbol.toString()] = 'value'; // 抛出 TypeError 错误
- The built-in
Symbol
values have special meanings, such asSymbol.iterator
,Symbol.hasInstance
etc., which are used to specify the default iterator of the object, custominstanceof
behavior, etc.
const arr = [1, 2, 3];
const iter = arr[Symbol.iterator]();
console.log(iter.next()); // 输出 { value: 1, done: false }
console.log(iter.next()); // 输出 { value: 2, done: false }
console.log(iter.next()); // 输出 { value: 3, done: false }
console.log(iter.next()); // 输出 { value: undefined, done: true }
Symbol
Values can be used as constants to avoid naming conflicts. For example, you can use aSymbol
value as the event name to ensure that it does not conflict with other event names.
const EVENT_A = Symbol('event_a');
const EVENT_B = Symbol('event_b');
// 发送事件 A
eventEmitter.emit(EVENT_A);
// 监听事件 B
eventEmitter.on(EVENT_B, () => {
// do something
});
To sum up, Symbol
it is a unique identifier that can be used as an object property name, and can be used to define constants, specify default iterators, etc. Its emergence makes the naming of object property names in JavaScript more flexible and rich.
arrow function
ES6 introduces Arrow Functions as a new function definition syntax. Arrow functions have some special syntax and behavior compared to traditional function definition methods.
Features are as follows:
-
Concise syntax: Arrow functions
=>
are defined using arrows ( ), omittingfunction
keywords and braces in the function body. If the function body has only one statement, the return keyword can be omitted and the result of the expression is returned implicitly.// 传统函数定义 function add(a, b) { return a + b; } // 箭头函数定义 const add = (a, b) => a + b;
-
Arrow functions do not have their own
this
,arguments
,super
ornew.target
. They inherit the corresponding values from the outer scope. This means that inside the arrow function,this
the context object pointed to is the context object when the function is defined, not the object when it is called.const person = { name: 'John', sayHello: function () { setTimeout(() => { console.log(`Hello, ${ this.name}!`); }, 1000); } }; person.sayHello(); // 输出 "Hello, John!"
-
Arrow functions cannot be used as constructors, and
new
objects cannot be instantiated using keywords. Arrow functions have noprototype
properties, sonew
object instances cannot be created using keywords.const Person = (name) => { this.name = name; // 错误:箭头函数不能用作构造函数 }; const john = new Person('John'); // 错误:无法使用new关键字实例化对象
-
If the arrow function has only one parameter, you can omit the parameter's parentheses; if there are no parameters or multiple parameters, you need to use parentheses.
// 一个参数 const greet = name => console.log(`Hello, ${ name}!`); // 没有参数 const sayHello = () => console.log('Hello!'); // 多个参数 const add = (a, b) => a + b;
Arrow functions simplify function definition in many scenarios, and are especially useful in handling callback functions, handling context binding, and simplifying function nesting. However, there are differences between arrow functions and traditional functions that need to be noted, particularly in this
their behavior when dealing with context.
Destructuring assignment
ES6’s destructuring assignment is a convenient syntax for extracting values from an array or object and assigning them to variables. It allows us to write code in a concise way and quickly extract the required values from complex data structures.
Destructuring assignment can be applied to arrays and objects. The two cases are explained in detail below:
-
Array destructuring assignment:
Array destructuring assignment allows us to extract values from an array according to a specific pattern and assign them to variables. Pattern matching is based on array position.
const [a, b, ...rest] = [1, 2, 3, 4, 5]; console.log(a); // 1 console.log(b); // 2 console.log(rest); // [3, 4, 5]
In the above example, we use array destructuring assignment to
[1, 2, 3, 4, 5]
assign the values in the array to variablesa
,b
and respectivelyrest
.a
andb
receive the first and second elements of the array respectively, whilerest
receives the remaining elements as a new array. -
Object destructuring and assignment:
Object destructuring assignment allows us to extract attribute values from the object and assign them to variables, matching by attribute name.
const person = { name: 'Alice', age: 25, address: { city: 'New York', country: 'USA' } }; const { name, age, address: { city, country } } = person; console.log(name); // 'Alice' console.log(age); // 25 console.log(city); // 'New York' console.log(country); // 'USA'
In the above example, we use object destructuring assignment
person
to extract the propertiesname
,age
,address.city
and from the objectaddress.country
and assign them to the corresponding variables.Note that colons
:
can be used to specify aliases for destructuring assigned properties. In the above example, weperson.address
assign the value of to a variableaddress
andaddress
further deconstructcity
and from itcountry
.
Destructuring assignment also supports default values, nested structures, ignoring certain elements and other functions, which can be used flexibly according to specific needs. It can improve code readability and writing efficiency when dealing with complex data structures.
rest parameters
ES6 introduces the concept of rest parameters (remaining parameters), which allows us to represent an indefinite number of parameters as an array. In function declarations, rest parameters are represented by three dots (…) followed by a parameter name. This makes it easy to handle extra parameters passed to the function.
The following is a detailed explanation of some characteristics and usage of rest parameters:
-
grammar:
function functionName(...rest) { // 函数体 }
In the function declaration, use
...rest
the form to define rest parameters.rest
is an array containing all additional parameters passed in when the function is called. -
Handling redundant parameters:
When multiple parameters are passed when a function is called, and only a few parameters are defined in the function declaration, the redundant parameters will be captured in the rest parameters.function sum(...rest) { let total = 0; for (let num of rest) { total += num; } return total; } console.log(sum(1, 2, 3, 4, 5)); // 15
In the above example,
sum
there is only one rest parameter in the function's parameter listrest
, but we can pass any number of parameters tosum
the function andrest
calculate the sum by iterating over the array in the function body. -
Rest parameter is used in combination with other parameters:
In a function declaration, the rest parameter can coexist with other parameters, but the rest parameter must be the last parameter.function foo(a, b, ...rest) { console.log(a); // 1 console.log(b); // 2 console.log(rest); // [3, 4, 5] } foo(1, 2, 3, 4, 5);
In the above example,
a
andb
are ordinary parameters,rest
but rest parameters, which receive additional parameters passed to the function. -
Application of rest parameters:
- Collect remaining parameters: When we are not sure how many parameters will be passed in when the function is called, we can use the rest parameter to collect the remaining parameters for processing in the function body.
- Alternative arguments object: Rest parameters in ES6 are more intuitive and easier to use. In contrast,
arguments
the object is an array-like object, and the rest parameter is a real array, and various methods of the array can be used. - Flexibility of function parameters: By using rest parameters, we can declare functions that receive any number of parameters without specifying a fixed number of parameters in advance.
Summary: ES6's rest parameters provide us with a way to handle an indefinite number of parameters, collect them into an array, and operate them in the function body. It makes function declaration more flexible, making handling redundant parameters more convenient and readable.
Set/Map
ES6 introduces two new data structures, Set
and , which provide a more convenient and efficient way to deal with data collections and key-value pairs.Map
-
Set:
- Set is an unordered and non-repeating collection of data.
- Its member values are unique and will not be repeated.
- Any type of value can be stored, including primitive values and reference values.
- Elements in a Set are not indexed and cannot be accessed by index.
- The main application scenarios are for deduplication and determining whether an element exists.
const set = new Set(); set.add(1); set.add(2); set.add(3); set.add(2); // 添加重复元素,但不会生效 console.log(set.size); // 3 console.log(set.has(2)); // true set.delete(3); console.log(set.size); // 2 set.clear(); console.log(set.size); // 0
-
Map:
- Map is a collection of key-value pairs, similar to an object.
- Its keys and values can be any type of data, including primitive values and reference values.
- The key-value pairs in Map are ordered.
- You can use the key to get the corresponding value.
const map = new Map(); const key1 = 'key1'; const key2 = { name: 'John' }; map.set(key1, 'value1'); map.set(key2, 'value2'); console.log(map.size); // 2 console.log(map.get(key1)); // 'value1' map.delete(key2); console.log(map.size); // 1 console.log(map.has(key2)); // false map.clear(); console.log(map.size); // 0
Map also provides iterator (Iterator) methods, such as
keys()
,values()
andentries()
, which can be used to traverse the keys, values, and key-value pairs of the Map.const map = new Map(); map.set('a', 1); map.set('b', 2); map.set('c', 3); for (let key of map.keys()) { console.log(key); // 'a', 'b', 'c' } for (let value of map.values()) { console.log(value); // 1, 2, 3 } for (let [key, value] of map.entries()) { console.log(key, value); // 'a' 1, 'b' 2, 'c' 3 }
Map can also accept an array as a parameter to initialize.
const array = [['a', 1], ['b', 2], ['c', 3]]; const map = new Map(array); console.log(map.get('a')); // 1
Set and Map provide efficient data processing methods and are suitable for scenarios where collections and key-value pairs need to be managed. They are designed and used in a way that makes operation more intuitive and efficient, as well as allowing for better performance and scalability. ## let/const
template string
ES6 introduces template strings (Template Strings), which provides a more convenient and flexible way to process strings.
A template string is a string surrounded by backticks (`) and supports the following features:
-
String Interpolation:
Use${}
syntax to insert variables or expressions into template strings.const name = 'John'; const age = 30; const message = `My name is ${ name} and I'm ${ age} years old.`; console.log(message); // "My name is John and I'm 30 years old."
Internally
${}
it can be any JavaScript expression, including variables, function calls, operators, etc. -
Multiline strings:
Template strings can span multiple lines without using escape characters or concatenation operators.const multiline = ` This is a multiline string. `; console.log(multiline); /* "This is a multiline string." */
Multiline strings preserve indentation and newlines in template strings, making the code more readable.
-
Nested template strings:
Other template strings can be nested within template strings to build more complex strings.const name = 'John'; const message = `Welcome to our website, ${ name}! Today's special offer: Buy 1 get 1 free! Offer valid until ${ new Date().toLocaleDateString()}.`; console.log(message); /* "Welcome to our website, John! Today's special offer: Buy 1 get 1 free! Offer valid until 5/11/2023." */
In the above example,
${name}
nested within the outer template string,${new Date().toLocaleDateString()}
nested within the inner template string. -
Raw Strings:
Prefixing a template stringString.raw
creates a raw string that does not escape backslashes.const path = String.raw`C:\Users\John\Documents\file.txt`; console.log(path); // "C:\Users\John\Documents\file.txt"
In the above example, the backslash remains unchanged in the original string and is not escaped as a special character.
Template strings provide a more intuitive and convenient way to work with strings, especially when you need to insert variables or build complex text. Its use can improve the readability and maintainability of the code, and reduce the tedious operations of string concatenation and escaping.
spread operator
The spread operator (Spread Operator) in ES6 is a three consecutive dots (...) used to spread iterable objects (such as arrays, strings, or array-like objects).
The spread operator has the following main uses and features:
-
Array expansion:
The spread operator can expand an array into multiple independent elements.const arr = [1, 2, 3]; console.log(...arr); // 1 2 3
This makes it easy to pass elements of an array to a function or merge multiple arrays.
-
String expansion:
The spread operator can expand a string into individual characters.const str = 'hello'; console.log(...str); // "h" "e" "l" "l" "o"
This is useful for operations that require character-by-character processing of strings.
-
Object expansion:
The spread operator can expand an object into multiple key-value pairs.const obj = { x: 1, y: 2 }; console.log({ ...obj }); // { x: 1, y: 2 }
This can be used to copy objects, merge objects, or create new objects.
-
Parameter passing when calling a function:
The spread operator can pass elements of an array or array-like object as parameters of the function.function sum(x, y, z) { return x + y + z; } const numbers = [1, 2, 3]; console.log(sum(...numbers)); // 6
This avoids
apply()
the hassle of using or manually destructuring parameters. -
Shallow copies of arrays and objects:
The spread operator can be used to create shallow copies of arrays and objects.const arr = [1, 2, 3]; const arrCopy = [...arr]; const obj = { x: 1, y: 2 }; const objCopy = { ...obj };
This creates copies of the original arrays and objects rather than referencing the same data.
The spread operator provides a concise and flexible way to work with arrays, strings, and objects, making code more readable and maintainable. It is very useful in scenarios such as function calling, array merging, and object copying, and can greatly simplify the code for related operations.
Iterator/Generator
ES6 introduces the concepts of iterator and generator, which are used to process iterable objects and functions that generate iterable objects.
-
Iterator:
An iterator is an object that provides a way to sequentially access a collection of data. It has anext()
method that returns an object containingvalue
anddone
properties on each call.value
: Indicates the value currently returned by the iterator.done
: Indicates whether the iterator has traversed all elements. If so,true
it means that the iterator has ended, otherwisefalse
.
Iterators can be implemented manually, or you can use the built-in iterators provided by ES6 for iterable objects (such as arrays, strings, Sets, Maps, etc.).
const arr = [1, 2, 3]; const iterator = arr[Symbol.iterator](); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }
-
Iterable:
An iterable is an object with an iterator, a collection of data that can be iterated (traversed). Iterable objects must have aSymbol.iterator
method named that returns an iterator object.Built-in iterable objects include arrays, strings, Sets, Maps, etc.
const arr = [1, 2, 3]; const str = 'hello'; const set = new Set([1, 2, 3]); const map = new Map([['a', 1], ['b', 2], ['c', 3]]); console.log(arr[Symbol.iterator]); // [Function: values] console.log(str[Symbol.iterator]); // [Function: [Symbol.iterator]] console.log(set[Symbol.iterator]); // [Function: values] console.log(map[Symbol.iterator]); // [Function: entries]
-
Generator:
A generator is a special function that is defined usingfunction*
keywords and usesyield
statements in the function body to pause the execution of the function and return an iterator object.The generator function can gradually generate values through an iterator. Each time the method of the generator function is called
next()
, the next statement will be executedyield
and an object containingvalue
anddone
attributes will be returned.function* generator() { yield 1; yield 2; yield 3; } const iterator = generator(); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }