210423 Spread/Rest構文

10550 ワード

Spread/Rest構文


... 3点連続使用の構文

Spread syntax(...)


allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.
MDN
  • 関数のパラメータで配列
  • を伝達する
    複数の
  • アレイを統合する場合、主に
  • を使用します.
  • アレイの値
  • のみをコピー
    Itableとは?アレイ、String、Map、Set、HTML Collection、NoteListなどの循環可能なデータ構造
    It is commonly used when you want to add a new item to a local data store, or display all stored items plus a new addition.(as many times as you like)

    Spread in function calls

    console.log(...[10, 20, 30]); // console.log(10, 20, 30)으로 변환되어 실행됨
  • Replace apply()
    It is common to use Function.prototype.apply() in cases where you want to use the elements of an array as arguments to a function.
  • // apply()
    
    function myFunction(x, y, z) { }
    let args = [0, 1, 2];
    myFunction.apply(null, args); 
    
    // With spread syntax
    
    function myFunction(x, y, z) { }
    let args = [0, 1, 2];
    myFunction(...args);
    
    // the spread syntax can be used multiple times.
    
    function myFunction(v, w, x, y, z) { }
    let args = [0, 1];
    myFunction(-1, ...args, 2, ...[3]);
    
  • Apply for new operator
  • When calling a constructor with new it's not possible to directly use an array and apply(). However, an array can be easily used with new thanks to spread syntax
    let dateFields = [1970, 0, 1];  // 1 Jan 1970
    let d = new Date(...dateFields);

    Spread in array literals


    Just like spread for argument lists, ... can be used anywhere in the array literal, and may be used more than once.

    Copy an array

    let arr = [1, 2, 3];
    let arr2 = [...arr]; // like arr.slice()
    
    arr2.push(4);
    //  arr2 becomes [1, 2, 3, 4]
    //  arr remains unaffected
    
    배열을 복사할 때 참조 주소값이 아니라, 값만 복사하기 때문에! 별도의 배열로 복사해서 사용할 수 있다.
    
    arr[0] = 100; // change an element of the arr
    arr // [100 , 1, 2, 3]
    arr2 // [1, 2, 3, 4]
    
    ** 주의: deep cloning 관련 (Object.assign())

    A better way to concatenate arrays


    Append

    // Array.prototype.concat()
    
    let arr1 = [0, 1, 2];
    let arr2 = [3, 4, 5];
    arr1 = arr1.concat(arr2);
    
    //spread syntax
    
    let arr1 = [0, 1, 2];
    let arr2 = [3, 4, 5];
    arr1 = [...arr1, ...arr2];  //  arr1 is now [0, 1, 2, 3, 4, 5]
    
    // Note: Not to use const otherwise, it will give TypeError (invalid assignment)

    Insert

    // Array.prototype.unshift() 
    
    let arr1 = [0, 1, 2];
    let arr2 = [3, 4, 5];
    Array.prototype.unshift.apply(arr1, arr2)     //  arr1 is now [3, 4, 5, 0, 1, 2]
    
    //  spread syntax
    
    let arr1 = [0, 1, 2];
    let arr2 = [3, 4, 5];
    arr1 = [...arr2, ...arr1];       //  arr1 is now [3, 4, 5, 0, 1, 2]
    
  • 注意:スプレッドシート構文は「値」ではないため、変数に割り当てることはできません.
    const val = ...[10, 20, 30];//エラー:変数を割り当てることができません.
  • Spread in object literals


    Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than Object.assign().
    let obj1 = { foo: 'bar', x: 42 };
    let obj2 = { foo: 'baz', y: 13 };
    
    let clonedObj = { ...obj1 };       // Object { foo: "bar", x: 42 }
    
    let mergedObj = { ...obj1, ...obj2 };     // Object { foo: "baz", x: 42, y: 13 }
    --------------------------------------------------------------------------------
    let obj1 = { foo: 'bar', x: 42 };
    let obj2 = { foo: 'baz', y: 13 };
    const merge = ( ...objects ) => ( { ...objects } );
    
    let mergedObj1 = merge (obj1, obj2);        // Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }
    
    let mergedObj2 = merge ({}, obj1, obj2);     // Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
    
    it spreads an array of arguments into the object literal, due to the rest parameter.

    Only for iterables


    Objects themselves are not iterable, but they become iterable when used in an Array, or with iterating functions such as map(), reduce(), and assign()
    let obj = {'key1': 'value1'};
    let array = [...obj]; // TypeError: obj is not iterable

    Rest parameters

  • accept an indefinite number of arguments as an array
  • 関数に複数のパラメータを渡す際に主に(パラメータ数が分からない場合)
  • を用いる.
    function f(a, b, ...theArgs) {
       statement
    }

    A function definition can have only one ...restParam.

    foo(...one, ...wrong, ...wrong)       /// has to be only one!!!

    The rest parameter must be the last parameter in the function definition.

    foo(...wrong, arg2, arg3)
    foo(arg1, arg2, ...correct)         /// has to be last!!
    Rest parameters are real arrays; the arguments object is not.
    Rest parameters are Array instances, meaning methods like sort, map, forEach or pop can be applied on it directly;
    function myFun(a, b, ...manyMoreArgs) {
      console.log("a", a);
      console.log("b", b);
      console.log("manyMoreArgs", manyMoreArgs);
    }
    
    myFun("one", "two", "three", "four", "five", "six");
    
    // 질문: 콘솔은 순서대로 어떻게 찍힐까요?
    a one
    b two
    manyMoreArgs ["three", "four", "five", "six"]<--------An array!!!!!!
    -----------------------------------------------------------------------
    myFun("one", "two", "three")
    
    // a, "one"
    // b, "two"
    // manyMoreArgs, ["three"] <-- notice it's an array, even though there's just one value
    -----------------------------------------------------------------------
    myFun("one", "two")
    
    // a, "one"
    // b, "two"
    // manyMoreArgs, [] <-- yip, still an array
    rest arguments常に配列:渡されたパラメータがない場合は空の配列[]

    Argument length

    function fun1(...theArgs) {
      console.log(theArgs.length)
    }
    
    fun1()         // 0      <-------------Since theArgs is an array
    fun1(5)        // 1
    fun1(5, 6, 7)  // 3  

    ぶんぱいせっけいこうぞう


    MDN
    a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
    Spread構文を使用して値を分解し、変数に新しい値を割り当てます.
    「割り当て」(Association)文の左側で、元の変数から分解して割り当てる値を定義します.

    Array destructuring


    基本変数の割当て(デフォルト変数の割当て)
    var foo = ["one", "two", "three"];
    
    var [one, two, three] = foo;
    console.log(one); // "one"
    console.log(two); // "two"
    console.log(three); // "three"
    アサイメントと宣言の分離(宣言から分離されたアサイメント)
    変数の宣言が分離されても、構造を分解することで値が割り当てられます.
    var a, b;
    
    [a, b] = [1, 2];
    console.log(a); // 1
    console.log(b); // 2
    Default値(デフォルト)
    変数にデフォルト値を指定すると、分解値がundefinedの場合に使用されます.
    var a, b;
    
    [a=5, b=7] = [1];
    console.log(a); // 1
    console.log(b); // 7
    スワップ変数(スワップ変数値)
    2つの変数の値を交換できる構造分解式は1つだけです.
    構造分解を割り当てずに2つの値を交換する場合は、一時変数が必要です.(一部の低レベル言語ではXOR置換テクニックが提供されています)
    var a = 1;
    var b = 3;
    
    [a, b] = [b, a];
    console.log(a); // 3
    console.log(b); // 1
    関数から返されるParsing an array(解析関数から返される配列)
    関数は、以前はアレイを返すことができましたが、構造分解を使用すると、返されたアレイをより簡潔に処理できます.
    次の例では、f()は出力として配列を返し[1,2]、構造分解を1つだけ使用して値を解析できます.
    function f() {
      return [1, 2];
    }
    
    var a, b;
    [a, b] = f();
    console.log(a); // 1
    console.log(b); // 2
    Ignoringいくつかの戻り値(戻り値は無視)
    不要な戻り値は無視できます
    
    function f() {
      return [1, 2, 3];
    }
    var [a, , b] = f();
    console.log(a); // 1
    console.log(b); // 3
    
    **반환 값을 모두 무시할 수도 있습니다.**
    
    [,,] = f();
    Assigning the rest of an array to a variable
    When destructuring an array, you can unpack and assign the remaining part of it to a variable using the rest pattern
    const [a, b,...c] = [1, 2, 3, 4];
    console.log(a); // 1
    console.log(c); // [3, 4]
    Unpacking values from a regular expression match

    Object destructuring


    Basic assignment
    const user = {
        id: 42,
        is_verified: true
    };
    const {id, is_verified} = user;
    
    console.log(id); // 42
    console.log(is_verified); // true
    Assignment without declaration
    let a, b;
    
    ({a, b} = {a: 1, b: 2});
    **할당문 둘러싼 ( ... ); 필요** const {a, b} = {a: 1, b:2}와 같다
    
    Assigning to new variable names
    A property can be unpacked from an object and assigned to a variable with a different name than the object property.
    const o = {p: 42, q: true};
    const {p: foo, q: bar} = o;
    
    console.log(foo); // 42
    console.log(bar); // true
    
    const {p: foo} = o takes from the object o the property named p and assigns it to a local variable named foo.
    
    Default values
    const {a = 10, b = 5} = {a: 3};
    
    console.log(a); // 3
    console.log(b); // 5
    
    *Assigning to new variables names and providing default values
    const {a: aa = 10, b: bb = 5} = {a: 3};
    
    console.log(aa); // 3
    console.log(bb); // 5
    Unpacking fields from objects passed as a function parameter
    const user = {
      id: 42,
      displayName: 'jdoe',
      fullName: {
        firstName: 'John',
        lastName: 'Doe'
      }
    };
    
    function userId({id}) {
      return id;
    }
    
    function whois({displayName, fullName: {firstName: name}}) {
      return `${displayName} is ${name}`;
    }
    
    console.log(userId(user)); // 42
    console.log(whois(user));  // "jdoe is John"
    Rest in Object Destructuring
    let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
    a; // 10
    b; // 20
    rest; // { c: 30, d: 40 }