This series of blog posts is a summary of ES6 basic syntax usage, and any errors are welcome. ES6 includes Generator, Set/Map, Proxy, etc.

Asynchronous programming

The Javascript language is executed in a “single thread” environment.

Single-threaded means that you can only complete one task at a time. If there are multiple tasks, they must be queued, the first task completed, the next task executed, and so on.

The Javascript language divides the execution modes of the task into two types: Synchronous and Asynchronous.

“Synchronous mode” is the mode of the previous section, the latter task wait for the end of the previous task, and then execute, the execution sequence of the program is consistent with the order of tasks, synchronous; “Asynchronous mode” is completely different, each task has one or more of the callback function (the callback), before the end of a task, not to perform a task, after but the callback function, after a task is before the end of a task before execution, so the program execution order the order is not consistent with the task, asynchronous.

“Asynchronous mode” is very important. On the browser side, long operations should be performed asynchronously to prevent the browser from becoming unresponsive. The best example of this is Ajax operations. On the server side, “asynchronous mode” is even the only mode, because the execution environment is single-threaded, and if you allow all HTTP requests to be executed synchronously, the server performance deteriorates dramatically and quickly becomes unresponsive.

Asynchronous programming methods

Through the callback function

Advantages are simplicity, easy to understand and deploy; The disadvantages are unreadable and unmaintainable code, high Coupling between parts, confusing processes, and only one callback function specified for each task.

By event listening

The execution of tasks depends not on the order of the code, but on whether an event occurs.

With event monitoring, you can bind multiple events, and specify multiple callback functions for each event. Moreover, it can “decouple”, which is good for modularity. The disadvantage is that the entire program has to be event-driven, and the flow becomes very unclear.

Adopt a publish/subscribe model

We assume that there is a “signal center” that “publishes” a signal when a task completes, and that other tasks can “subscribe” to the signal center to know when they can start executing. This is called a publish-subscribe pattern, also known as an observer pattern.

This approach is similar in nature to “event listening”, but clearly superior to the latter. Because we can monitor the program by looking at the “message center” to see how many signals exist and how many subscribers each signal has.

Promise

I don’t want to repeat it. It’s here

Generator

Generator functions are an asynchronous programming solution provided by ES6

As the name implies, it is a generator, which is also a state machine with values and associated states. The generator returns an Iterator that manually iterates through related values and states to ensure correct execution order.

A generator is an object that generates one of a series of values at a time. To create a generator, you can have a function return a particular value using the yield operator. For functions that return a value using the yield operator, a new instance of Generator is created and returned when called. You can then call the next() method on this instance to get the first value of the generator. At this point, the original function is executed, but the flow of execution stops at yield, returning only the specified value. From this perspective, yield is similar to return. If the next() method is called again, the code after the yield statement in the original function continues to execute until the next yield statement is encountered.

Use 1.

Generator functions are different from normal functions in that they can be paused, so the function name is preceded by an asterisk.

The whole Generator function is a encapsulated asynchronous task, or a container for asynchronous tasks. Where asynchronous operations need to be paused, use the yield keyword.

  • yieldKeywords enable the logic within the Generator to be cut into multiple parts.
function* listNum() {
    let i = 1;
    yield i;
    i++;
    yield i;
    i++;
    yield i;
}
const num = listNum();
console.log(listNum());
Copy the code

  • By calling the iterator objectnextMethod executes a section of code that returns the state defined in that section
const num = listNum();
console.log(num.next());
console.log(num.next());
console.log(num.next());
Copy the code

The above code defines a generator function for listNum that returns an iterator object.

After the next method is called, the first yield statement is executed within the function, printing the current state done (whether the iterator is traversed) and the corresponding value (usually the result of the operation after the yield keyword).

Per callnextIs executed onceyieldStatement, and pause there.

2. The Generator function iterates the number group

2.1 You can see that if the next method is not called, the code wrapped in the function is not executed immediately (console.log(arr) in the following example; Not running)

let arr = [
  {name: 'zs',age: 38,gender: 'male'},
  {name: 'yw',age: 48,gender: 'male'},
  {name: 'lc',age: 28,gender: 'male'},];function* loop(arr) {
  console.log(arr);
  for(letitem of arr){ yield item; }}let repoGen = loop(arr);
console.log(repoGen);
Copy the code

2.2 The code in the generator function is executed only when the next method is called

let repoGen = loop(arr);
console.log(repoGen.next());
console.log(repoGen.next());
console.log(repoGen.next());
Copy the code

2.3 When the done flag is true after traversal, print the generator function and its state has changed to Closed

let repoGen = loop(arr);
console.log(repoGen);
console.log(repoGen.next());
console.log(repoGen.next());
console.log(repoGen.next());
console.log(repoGen.next());
console.log(repoGen);
Copy the code

3. Differences between Generator functions and common functions

3.1 After calling a Generator function, an iterator object is returned regardless of whether the function returns a value. 3.2 After calling a Generator function, the code encapsulated in the function is not executed immediately

4.next()Pass arguments in the call

When you call the next method, you can pass a single parameter, which is passed to the previous yield. Note that next() is not passed the first time, but only the second time

4.1 After the first call to Next, the return value of “one” is 1. However, in the second call to next, “one” is actually undefined. Since the generator does not automatically store the corresponding variable value, we need to specify it manually. On the third call to next, yield 3 * two is executed and the last yield return value two is set to 2 by passing the parameter

function* showNumbers() { var one = yield 1; var two = yield 2 * one; yield 3 * two; } var show = showNumbers(); console.log(show.next().value); // 1 console.log(show.next().value); // NaN console.log(show.next(2).value); / / 6Copy the code

I can’t write it.

function* gen() {
  console.log("123");
  let res = yield "aaa";

  console.log(res);
  console.log("567");
  yield 1 + 1;

  console.log("789");
  yield true;
}
letit = gen(); console.log(it.next()); {value: 123;"aaa".done: false}
console.log(it.next("666")); // Pass the argument to res, output 666; Output 567; {value: 2,done: false}
console.log(it.next()); //{value: true.done: false}
console.log(it.next()); //{value: undefined, done: true}
Copy the code

5. Application scenarios of Generator functions

5.1 Let a function return multiple values

 function* calculate(a, b) {
     yield a + b;
     yield a - b;
 }
 let it = calculate(10, 5);
 console.log(it.next().value);
 console.log(it.next().value);
Copy the code

5.2 Using synchronous flows to represent asynchronous operations (workflow for handling Ajax requests) 5.3 Since Generator functions are traverser-generating functions, you can assign Generator to the Symbol. Iterator property of an object so that the object has an Iterator interface.

6.for… of

for… The of loop automatically iterates over the Iterator generated by the Generator function, and there is no need to call the next method.

function *foo() {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
  return 6;
}

for (let v of foo()) {
  console.log(v);
}
// 1 2 3 4 5
Copy the code

The code above uses for… The of loop displays the values of the five yield statements in turn. Note here that once the next method returns an object with the done attribute true, for… The of loop terminates and does not contain the return object, so the 6 returned by the return statement above is not included in the for… In the loop of.

Set data structure

ES6 provides a new data structure, Set. It is similar to an array, but the values of the members are unique and there are no duplicate values.

Unlike arrays, Set data structures cannot retrieve elements by index.

Use 1.

The Set itself is a constructor used to generate the Set data structure.

Format: new Set([iterable]);

let list = new Set();
console.log(list);

let color = new Set(['red'.'yellow'.'green']);
console.log(color);
Copy the code

2. Common methods of Set data structure

2.1 the add (value)

Adds an element to the end of the Set. Returns the Set object.

Note: Adding the same member is ignored

letlist = new Set(); [1, 2, 3, 4, 5]. The map (item = > list. Add (item)); console.log(list);Copy the code

2.2. The size

Returns the total number of members of a Set instance.

letlist = new Set(); [1, 2, 3, 4, 5]. The map (item = > list. Add (item)); console.log(list.size); / / 5Copy the code

2.3 the delete (value)

When a value is deleted, a Boolean value is returned indicating whether the deletion was successful.

letlist = new Set(); [1, 2, 3, 4, 5]. The map (item = > list. Add (item)); console.log(list.delete(5)); //true
Copy the code

2.4. The clear

Removes all elements from Set, with no return value.

letlist = new Set(); [1, 2, 3, 4, 5]. The map (item = > list. Add (item)); list.clear(); console.log(list); //Set(0) {}Copy the code

2.5 from the (value)

Returns a Boolean value indicating whether the value exists in the Set.

letlist = new Set(); [1, 2, 3, 4, 5]. The map (item = > list. Add (item)); console.log(list.has(1)); //true
Copy the code

3.Set is traversable

3.1.values () returns a new iterator object that contains the values of all elements in Set in insertion order.

letlist = new Set(); [1, 2, 3, 4, 5]. The map (item = > list. Add (item)); console.log(list.values());Copy the code

3.2 Call the next() method of the traverser to implement traversal

letlist = new Set(); [1, 2, 3, 4, 5]. The map (item = > list. Add (item));let it = list.values();
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
Copy the code

The 3.3 Set method deploys the Iterator interface, so for of can also be used to iterate

for(let key of list){
  console.log(key);
}
Copy the code

Traversal with forEach

list.forEach((item,key,ownSet) => {
  console.log(item, key, ownSet);
})
Copy the code

4. Use Set to de-duplicate arrays

The interview often asks: using ES5 method and ES6 respectively to achieve array deduplication

We first convert an array to a Set structure for de-duplication, since sets are iterable, and then use the extension operator to convert a Set to an array

let,2,4,6,4,3,6,8 arr = [1];letnumberSet = new Set(arr); // Array Set console.log(numberSet);letuniqueArr = [...numberSet]; //Set console.log(uniqueArr);Copy the code

Array.prototype.unique = function () {
    return [...new Set(this)];
};
Copy the code

WeakSet

WeakSet structure is similar to Set, which is also a collection of non-repeating values.

WeakSet structure has the following three methods.

.add(value) : Adds a new member to the WeakSet instance. .delete(value) : Clears the specified member of the WeakSet instance. .has(value) : Returns a Boolean value indicating whether a value is in a WeakSet instance.

Difference between WeakSet and Set

  • WeakSet members can only be objects, not other types of values.
let lucy = {region:'America',age: 18};
let lily = {region:'Canada',age: 20};

let person = new WeakSet([lucy,lily]);
person.add('lucas');
console.log(person); //Invalid value used in weak set
Copy the code
  • WeakSet is not traversal.
for(let key of person){
  console.log(key); //person is not iterable
}
Copy the code
  • WeakSet nosizeProperty, there is no way to traverse its members.
  • WeakSet noclear()Method, but has the effect of self-cleaning, to avoid memory leaks.
let lucy = {region:'America',age: 18};
let lily = {region:'Canada',age: 20};

let person = new WeakSet([lucy,lily]);
console.log(person);
Copy the code

let lucy = {region:'America',age: 18};
let lily = {region:'Canada',age: 20};

let person = new WeakSet([lucy,lily]);
console.log(person);
lily = null;
console.log(person);
Copy the code

Map data structure

Map objects hold key-value pairs. Any value (object or raw value) can be a key or a value.

The Map type, also known as a simple Map, has only one purpose: to hold a set of key-value pairs. Developers often use ordinary objects to hold key-value pairs, but the problem is that doing so can easily confuse keys with native properties. Simple mapping can separate keys and values from object attributes to ensure the safe storage of object attributes.

Map data structure provided by ES6. It is a collection of key-value pairs similar to objects, but the range of “keys” is not limited to strings. Values of all types (including objects) can be used as keys. In other words, the Object structure provides string-value mapping, and the Map structure provides value-value mapping, which is a more complete Hash structure implementation. If you need key-value data structures, Map is better than Object.

Use 1.

  • Grammar:new Map([iterable])
  • Iterable can be an array or any other Iterable object whose elements are key-value pairs (an array of two elements, for example: [[1, ‘one’],[2, ‘two’]]). Each key-value pair is added to the new Map. Null will be treated as undefined.
const people = new Map();
people.set('lucy', 18); people.set('lily', 20); console.log(people);Copy the code

2. Common methods of Map data structure

The size property returns the total number of Map structure members.

2.2 Set (Key, value) The set method sets the key value corresponding to a key and returns the entire Map structure. If the key already has a value, the key value is updated, otherwise the key is generated.

2.3 GET (Key) The GET method reads the key corresponding to the key. If the key cannot be found, undefined is returned.

2.4 HAS (key) The HAS method returns a Boolean value indicating whether a key is in the Map data structure.

2.5 delete(key) The delete method deletes a key and returns true. If deletion fails, return false.

2.6. clear() The clear method clears all members without returning a value.

3.Map is traversal

const people = new Map();
people.set('lucy', 18); people.set('lily', 20); people.set({},3);for(let key of people){
  console.log(key);
}
Copy the code

people.forEach((value,key,map) => {
  console.log(value, key, map);
})
Copy the code

4. Difference between Map and Object

A Map’s key can be any type of value, an object, a function, and so on

  • The keys of an Object can only be strings or Symbols, while the keys of a Map can be any values, including functions, objects, and basic types.
  • Keys in a Map are ordered, while keys added to objects are not. Therefore, when traversing it, the Map object returns key values in the order in which they were inserted.
const people = new Map();
people.set('lucy', 18); people.set('lily', 20); people.set({},3); console.log(people);Copy the code

5. Interconversion with other data structures

5.1 Converting a Map to an Array The most convenient way to convert a Map to an array is to use the extension operator (…). .

const people = new Map();
people.set('lucy', 18); people.set('lily', 20); people.set({},3);let arr = [...people];
console.log(arr);
Copy the code

Array to Map


new Map([[true, 7], [{foo: 3}, ['abc']]])
Copy the code

5.3 Map Into Objects If all Map keys are strings, they can be converted into objects.

function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}
Copy the code

5.4 Converting an Object to Map

function objToStrMap(obj) {
  let strMap = new Map();
  for (let k of Object.keys(obj)) {
    strMap.set(k, obj[k]);
  }
  return strMap;
}
Copy the code

WeakMap

The difference between WeakMap and Map lies in:

  • WeakMap only accepts objects as key names (except null) and does not accept values of other types as key names
  • WeakMap cannot traverse
  • When a WeakMap element is not referenced elsewhere, the garbage collection mechanism cleans it up automatically

There are two main differences between WeakMap and Map in API:

  • No traversal operation(i.e., nokey(),values()andentries()Method), neithersizeProperties;
  • Cannot be empty, that is, not supportedclearMethods. This is related to the fact that the key of WeakMap is not included in the reference and is ignored by the garbage collection mechanism. Therefore, WeakMap has only four methods available:get(),set(),has(),delete().

Proxy

Proxy objects are used to define custom behavior for basic operations (such as property lookups, assignments, enumerations, function calls, etc.). It helps us override some of the default methods on objects and define our own business logic.

Proxies can be used when you need to expose the API while avoiding direct manipulation of the underlying data by consumers.

Use 1.

  • Grammar:let p = new Proxy(target, handler);
  • Parameters:

    targetA target object wrapped in a Proxy (which can be any type of object, including a native array, a function, or even another Proxy).

    handlerAn object whose properties are functions that define the behavior of the agent when an operation is performed.

All uses of Proxy objects are in this form, except for the handler arguments. The new Proxy() parameter represents the generation of a Proxy instance, the target parameter represents the target object to intercept, and the handler parameter is also an object used to customize the interception behavior.

2.Proxy instance method

get()

Used to intercept a read of a property

const person = {name: 'ghk',age: 18};
const personProxy = new Proxy(person,{
get(target, key){
  console.log(target, key); //{name: "zs", age: 18} "name"
  returntarget[key].toUpperCase(); }}); personProxy.name ='zs';
console.log(personProxy); //Proxy {name: "zs", age: 18}
console.log(personProxy.name); //ZS
Copy the code

set()

The set method intercepts an assignment to an attribute.

const person = {name: 'ghk',age: 18};
const personProxy = new Proxy(person,{
set(target, key, value){
  if(typeof value === 'string'){ target[key] = value.trim(); }}}); personProxy.string =' this is a test ';
console.log(personProxy.string); //THIS IS A TEST
Copy the code