preface

It’s been half a month, and I’m finally back to updating. Although it is only the second one, I will continue to work hard and will not give up updating. If there is anything wrong with the article or you have more suggestions, welcome and look forward to your message to me, every message you leave may become my help for progress, thank you very much. So let’s just cut to the chase and get started.

concept

Deconstructing assignment, as the name suggests, is to untangle a structure and then take values out of it and use them to assign values to variables. So deconstruction assignment is divided mainly by data type.

Destruct assignment of arrays

Var [a, b, c] = [1, 2, 3].Copy the code

The above code is the simplest array deconstruction assignment, but can also be seen as another way to display data. For example, the code above is the same as the code below.

var a=1,b=2,c=3;
Copy the code

So the main thing about deconstructing assignment is that it allows us to simplify the process of extracting values.

In essence, this is “pattern matching,” in which the variables on the left are assigned to the values on the right. Such as:

let [a,[[b],c]] = [1,[[2],3]];
a //1
b //2
c //3
Copy the code

And as long as the pattern is the same, even if the variable or value of part of the position is empty, it can still be matched.

let[a, b] = [1,2,3]; a //1 b //3let[a, b, c] = [1, 2]; a//1 b//2 c//undefindCopy the code

When the deconstruction fails, that is, the variable is not assigned, or undefind is assigned directly, the value of the variable is equal to undefind.

When the matching patterns on both sides are the same and of different lengths, the deconstruction assignment is called incomplete deconstruction. Although it is called incomplete deconstruction, it is still successful.

let[a, b] = [1, 2, 3]. a //1 b //2Copy the code

There is a premise mentioned above, that is, the pattern is the same, yes, this is a point to pay attention to. Destructuring assignments will cause errors when the two modes are different.

let [a] = 1;
let [b] = false;
let [c] = {};
Copy the code

Without rigor, we can say that when the two data types are different, the deconstruction assignment will report an error.

Any data structure that has an Iterator interface can be assigned in the form of an array. The Iterator interface provides traversal commands for… It is not difficult to guess that array deconstruction assignment is actually an operation of iterating variables through a loop and then assigning values one by one.

function* fibs() {
  let a = 0;
  let b = 1;
  while (true) { yield a; [a, b] = [b, a + b]; }}let [first, second, third, fourth, fifth, sixth] = fibs();
sixth // 5
Copy the code

The above is ruan Yifong ES6 introduction inside the example, because personal is still not clear which specific data structure has Iterator interface, so here directly carry it.

The default value

let [a=1] = [];
a//1
Copy the code

When unpacking an assignment, you can set a default value. If undefind is located in the unpacking assignment room, the variable will be assigned a default value.

Note that ES6 internally uses the strict equality operator (===) to determine whether a position has a value, which I generally refer to as the congruent symbol. So, contrary to the usual judgment, the default value is valid only if the value of the array member used for assignment is undefined (strictly equal to undefined).

let [a=1] = [undefined];
a//1

let [b=1] = [null];
b//null

let [c=1] = [NaN];
c//NaN
Copy the code

When using default values, you can also refer to other variables that are destructively assigned, but only if that variable is declared.

let [a=1,b=a] = [];
a//1
b//1

let [a=b,b=1] = [];
//ReferenceError: b is not defined

var [a=b,b=1] = [];
a//undefined
b//1
Copy the code

Object destructuring assignment

let { a,b } = { a:'1',b:'2'};
a //'1'
b //'2'
Copy the code

The biggest difference between object deconstruction assignment and array deconstruction assignment is that array deconstruction assignment, variable value is determined by position; In the object deconstruction assignment, the value of a variable is determined by the name of the attribute. Only when the variable is the same as the name of the attribute can the value be obtained.

let { a , b } = { b : '2' , a : '1' };
a //1
b //2

let { a } = { b: '1' , c: '2' };
a//undefined
Copy the code

When the variable name is inconsistent with the attribute name, but a deconstruction assignment is required, you can use the variable to perform another deconstruction assignment.

let obj = { a : '1' , b : '2' };
let { a : c , b : d } = obj;
c //'1'
d //'2'
Copy the code

And, in the process, what’s actually being assigned are c and D. Whereas a and B are patterns that act as a sort of intermediary and are not actually assigned.

let { a : b } = { a : '1'};
a //ReferenceError: a is not defined
b //'1'
Copy the code

Destruct assignment of objects, like destruct assignment of arrays, can also be used for nested objects.

let a = {
    b : [
        '1',
        { c : '2'}};let {
    b : [
        x ,
        { c }
    ]
} = a;

x // '1'
c // '2'
b // ReferenceError: b is not defined
Copy the code

B is just the mode, so it cannot be assigned.

The default value

Destruct assignment of objects also has default values, which are set in the same way as arrays, rather than using the internal writing of objects.

let { a = 1} = {};
a // 1

let { b : 1 } = {};
//SyntaxError: Invalid destructuring assignment target
Copy the code

The default value is valid under the same conditions as array deconstruction assignment, the value of the property must be exactly equal to undefined to be valid.

let { a = 1 } = { a : undefined };
a //1 

let { b = 1 } = { b : null };
b // null

let { c = 1 } = { c : NaN };
c // NaN
Copy the code

When using destruct assignment for nested objects, be aware that an error will be reported if the parent property of the child object does not exist. This is also a common error that I find in my work, which needs more attention. This is especially true when using multi-tier structures such as res.data.id.

let { a: {b} }  = { c : '1' };
TypeError: Cannot destructure property `b` of 'undefined' or 'null'
Copy the code

When destructuring assignments using objects, be careful if you want to destruct assignments to already declared variables.

let a;
{a} = {a:1};
//SyntaxError: Unexpected token =
Copy the code

This is because the JavaScript engine treats {a} as a block of code, causing syntax errors. Avoid curly braces at the beginning of a line.

let a;
({a} = {a:1});
a // 1
Copy the code

Since arrays are special objects in nature, they can be destructively assigned to object properties.

let a = [1, 2, 3];
let {0 : b, 2: c} = a;
b // 1
c // 3
Copy the code

The 0 and 2 in the second line of code represent the position of the array, which can be easily interpreted as the following:

letA = [1, 2, 3];let b =  a[0];
let c =  a[2];
Copy the code

Destruct assignment of a string

Strings can also be destructively assigned, because the string is converted to an array-like object.

let [a, b, c, d, e] = 'hello';
a // 'h'
b // 'e'
c // 'l'
d // 'l'
e // 'o'
Copy the code

If this process looks familiar, it can be interpreted as the following code:

let x = 'hello'; a = x[0]; b = x[1]; c = x[2]; .Copy the code

Deconstructive assignment of values and Bores

When deconstructing an assignment, if there is a value or a Boolean to the right of the equals sign, it is converted to an object first.

let {toString:a} = 123;
a === Number.prototype.toString // true

let {toString:a} = 123;
a === Boolean.prototype.toString // true
Copy the code

The rule for deconstructing assignment is that if the value to the right of the equals sign is not an object or array, it will be converted to an object first. Because undefined and NULL cannot be converted to objects, an error is reported when destructing them.

let { a:b } = undefined;
//TypeError: Cannot destructure property `a` of 'undefined' or 'null'

let { a:b } = null;
//TypeError: Cannot destructure property `a` of 'undefined' or 'null'
Copy the code

Destruct assignment of function arguments

function add({x,y]){
    returnx+y; }} the add ({1, 2); / / 3Copy the code

The argument to add is ostensibly an array, but the moment it is passed in, the array argument is deconstructed into two variables, x and y.

Function arguments can also be destructed with default values.

function move({x=0,y=0} = {} ) {
    return[x,y]; } move({x:1}); / / (1, 0]; move({}); / / (0, 0),Copy the code

There is another way of writing the function argument deconstruction, which leads to another result.

function move({x,y} = {x:0,y:0} ) {
    return[x,y]; } move({x:1}); // [1,undefined]; move({}); // [undefined,undefined]; move(); / / [0, 0]Copy the code

The above code sets default values for the move function arguments, not for the deconstructed x and y values, so the result is different.

parentheses

The question is whether parentheses are used when destructuring assignments.

The rules of ES6 state that parentheses should not be used if they are likely to cause ambiguity in deconstruction.

However, because the criteria of this rule are not easy to measure and discern, parentheses are generally avoided.

A case where parentheses cannot be used

  1. Variable declaration statement

    let [(a)] = [1];
    let{x: (c)} = {}; // The above two lines of code display undefinedlet ({x: c}) = {};
    let {(x: c)} = {};
    let {(x): c} = {};
    let{ o: ({ p: p }) } = { o: { p: 2 } }; // The above four lines of code will report an error.Copy the code

    This happens in the above code mainly because they are variable declaration statements and the schema cannot use parentheses.

  2. Function arguments Function arguments are also variable declarations and therefore cannot be parentheses.

    function a( [ ( b ) ] ) { return c; }
    Copy the code
  3. The mode of the assignment statement

    ( { a:b } ) = { a:1 };
    
    [ ({a:b}) , { c:d } ] = [{},{}];
    Copy the code

    Either enclosing the entire schema in parentheses or enclosing part of the schema in parentheses results in an error.

Deconstruct the purpose of assignment

  1. Swap the values of variables

    let a = 1;
    let b = 2;
    [a,b] = [b,a]
    Copy the code
  2. Returns multiple values from a function

    Destructuring assignments makes it easy to retrieve multiple return values from arrays or objects.

    function arr() {return[1, 2, 3]; }let[a,b,c] = arr(); // Return an arrayfunction arr() {
        return {
            a:1,
            b:2
        };
    }
    let { a,b } = arr();
    Copy the code
  3. Definition of function parameters Destructuring assignment makes it easy to map a set of parameters to variable names.

    // Arguments are an ordered set of valuesfunctionf([a, b, c]) { ... }f([1, 2, 3]); // Arguments are an unordered set of valuesfunction f({a, b, c}) { ... }f({z: 3, y: 2, x: 1});
    Copy the code
  4. Extracting JSON Data When extracting DATA from JSON objects, deconstructing assignments can be very simple and fast, making the code more concise.

    let jsonData = {
      id: 42,
      status: "OK",
      data: [867, 5309]};
    
    let { id, status, data: number } = jsonData;
    
    console.log(id, status, number);
    Copy the code
  5. Default values for function arguments By using destructive assignment, the entire code is much cleaner when assigning default values to function arguments.

    jQuery.ajax = function (url, {
      async = true,
      beforeSend = function () {},
      cache = true,
      complete = function () {},
      crossDomain = false,
      global = true} = {}) {// Set the default value} = {}) {Copy the code
  6. As mentioned above, we can use destruct assignment for objects that have an Iterator interface. Here, we can get key names and values quickly by deconstructing assignments.

    const map = new Map();
    map.set('first'.'hello');
    map.set('second'.'world');
    
    for (let [key, value] of map) {
      console.log(key + " is "+ value); } // first is hello // second is worldCopy the code
  7. When loading a module, you need to specify which methods to input. Deconstructing assignment makes the input statement very clear.

    const { SourceMapConsumer, SourceNode } = require("source-map");
    Copy the code

conclusion

When using deconstructed assignment, the overall feel is a simplification of the traversal process. Personally, the biggest effect is to simplify the process of similar logic code, so as to slim the code.

At the same time, some of the details in the original article were found to be wrong. For example, the first point in the case where parentheses cannot be used, the first two lines in the sample code do not report an error, but instead show undefined.

Let [(a)] = [1]; let [(a)] = [1]; [(a)] = [1]

Refer to the article

ECMAScript 6 Getting started: Destructively assigning variables