210423_Spread/Rest 문법

Bitnara Lee·2021년 4월 23일
0

Spread/Rest 문법

... 점(dot) 세개를 연달아 사용하는 문법

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

  • 함수의 매개변수로 배열 전달
  • 배열 여러 개를 병합할 때 주로 사용
  • 배열의 '값'만 복사

* Iterable이란? Array, String, Map, Set, HTMLCollection, NodeList 등 이터러블 형식에 맞는 순회 가능한 자료구조

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  

Destructuring assignment(구조분해)

MDN

a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

Spread 문법을 이용하여 값을 해체한 후, 개별 값을 변수에 새로 할당하는 과정
할당문의 좌변에서 사용하여, 원래 변수에서 어떤 값을 분해해 할당할지 정의합니다.

Array destructuring

Basic variable assignment(기본 변수 할당)

var foo = ["one", "two", "three"];

var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"

Assignment separate from declaration(선언에서 분리한 할당)
변수의 선언이 분리되어도 구조 분해를 통해 값을 할당.

var a, b;

[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2

Default values(기본값)
변수에 기본값을 할당하면, 분해한 값이 undefined일 때 그 값을 대신 사용합니다.

var a, b;

[a=5, b=7] = [1];
console.log(a); // 1
console.log(b); // 7

Swapping variables(변수 값 교환하기)
하나의 구조 분해 표현식만으로 두 변수의 값을 교환할 수 있습니다.

구조 분해 할당 없이 두 값을 교환하려면 임시 변수가 필요합니다. (일부 로우 레벨 언어에서는 XOR 교체 트릭을 사용할 수 있습니다)

var a = 1;
var b = 3;

[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1

Parsing an array returned from a function(함수가 반환한 배열 분석)
함수는 이전부터 배열을 반환 가능했지만 but 구조 분해를 사용, 반환된 배열에 대한 작업을 더 간결하게 수행

아래 예제에서 f()는 출력으로 배열 [1, 2]을 반환하는데, 하나의 구조 분해만으로 값을 분석할 수 있습니다.

function f() {
  return [1, 2];
}

var a, b;
[a, b] = f();
console.log(a); // 1
console.log(b); // 2

Ignoring some returned values(반환 값 무시)
필요하지 않은 반환 값을 무시가능


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 }
profile
Creative Developer

0개의 댓글