[JS] #4 변수

spread

const list = [21, 22];
console.log([11, ...list, 12]); 
const obj = {key: 50};
console.log({...obj});
// [11,21,22,12]
// {key: 50}
  • Syntax: [...iterable]
  • [...varName] 처럼 [ ]안에 점(.) 3개를 작성하고 이어서 이터러블 오브젝트를 작성합니다.
  • 이터러블 오브젝트를 하나씩 전개합니다.
  • {key: value}의 Object가 이터러블 오브젝트는 아니지만 전개가 가능합니다.

Array spread

const one = [21, 22];
const two = [31, 32];
const result = [11, ...one, 12, ...two];
console.log(result);
consoel.log(result.length);
// [11,21,22,12,31,32]
// 6
  • spread 대상 배열을 작성한 위치에 엘리먼트 단위로 분리 및 전개합니다.
const one = [21, 22];
const result = [11, 12, ...one];
console.log(result);
console.log(result.length);
// [11, 12, 21, 22]
// 4
  • 값이 대체되지 않고 전개됩니다.
    ⇒ 만약, 값이 대체되는 것이면 [11, 12, [21, 22]]로 이차원 배열이 되고, length는 3이 되게 됩니다.

push(...spread)

let result = [21, 22];
const five = [51, 52];
result.push(...five);
console.log(result);
result.push(..."abc");
console.log(result);
// [21, 22, 51, 52]
// [21, 22, 51, 52, a, b, c]
  • push( ) 파라미터에 spread 대상을 작성할 수 있습니다.
  • 배열 끝에 대상을 분리하여 첨부합니다.

String spread

const target = "ABC";
console.log([...target]);
// [A, B, C]
  • spread 대상 문자열을 작성한 위치에 문자 단위로 전개합니다.
    ⇒ target의 ABC를 문자 단위로 분리하여 전개합니다.

Object spread

const one = {key1: 11, key2: 22};
const result = {key3: 33, ...one};
console.log(result);
// {key3: 33, key1: 11, key2: 22}
  • spread 대상 Object를 작성한 위치에 프로퍼티 단위로 전개합니다.
    ⇒ ...one 은 one오브젝트의 프로퍼티를 전개합니다.
const one = {key1: 11, key2: 22};
const result = {key1: 33, ...one};
console.log(result);
// {key1: 11, key2: 22}
// const check = [...one];  ---  error
  • 프로퍼티의 이름이 같을경우 값을 대체합니다.
    ⇒ one의 key1과 result의 key1은 프로퍼티 이름이 같기에 뒤에 작성한 one의 프로퍼티 내용으로 대체됩니다. 그래서 key1은 33이 아닌 11이 출력됩니다.
    ⇒ const check = [...one]; one은 빌트인 오브젝트이기에 이터러블 오브젝트가 아니므로 대괄호 형태로 작성하면 에러가 발생합니다.

Rest 파라미터

function spread

호출하는 함수의 파라미터에 spread대상을 작성합니다.

function add(one, two, three) {
  console.log(one + two + three);
};
const values = [10, 20, 30];
add(...values);
// 60
  • 처리 순서 및 방법
    • 함수가 호출되면 우선, 파라미터 배열을 엘리먼트 단위로 전개
    • add(...values) → add(10, 20, 30); 이와같이 전개
    • 전개한 순서대로 파라미터 값으로 넘겨줍니다.
    • 호출받는 함수의 파라미터에 순서대로 매핑됩니다.

rest 파라미터

분리하여 받은 파라미터를 배열로 결합합니다.
spread: 분리, rest: 결합
syntax: function(param, paramN, ...name)

function point(...param) {
  console.log(param);
  console.log(Array.isArray(param));
}
const values = [10, 20, 30];
point(...values);
// [10, 20, 30]
// true
  • 작성 방법

    • 호출받는 함수의 파라미터에 ...에 이어서 파라미터 이름 작성을 합니다.
    • 호출한 함수에서 보낸 순서로 매핑합니다.

    ⇒ point(...values) → point(10, 20, 30)이 되어 호출합니다.
    ⇒ rest 파라미터로 다시 결합하여 param = [10, 20, 30]이 됩니다.

function point(ten, ...rest) {
  console.log(ten);
  console.log(rest);
};
const values = [10, 20, 30];
point(...values);
// 10
// [20, 30]
  • 파라미터와 Rest파라미터를 혼합 사용할 수 있습니다.
    ⇒ point(...values) → point(10, 20, 30)이 되어 호출합니다.
    ⇒ point에서는 첫번째 파라미터인 10을 ten에 할당합니다.
    ⇒ 나머지 20, 30을 ...rest 파라미터로 결합하여 최종적으로는 point(10, [20,30])으로 받게 됩니다.

Array-like

Object 타입이지만 배열처럼 이터러블 가능한 오브젝트입니다. for()문으로 전개할 수 있습니다.

const values = {0: "가",1:"나", 2:"다", length: 3};
for(let k = 0; k< values.length; k++){
  console.log(values[k]);
};
  • 작성 방법

    • 프로퍼티key 값을 0부터 1씩 증가하며 프로퍼티 값 작성
    • length에 전체 프로퍼티 수 작성

    ⇒ length 프로퍼티는 전개되지 않습니다(하면 안됩니다)
    ⇒ for~in문으로 전개할 경우 length 프로퍼티도 전개됩니다.

rest와 arguments의 차이점

  • Argument 오브젝트
    • 파라미터 작성에 관계없이 전체를 설정합니다.
    • Array-like 형태 : Array 메소드를 사용할 수 없습니다.
    • __proto__가 Object 입니다.
  • rest 파라미터
    • 매핑되지 않은 나머지 파라미터만 설정합니다.
    • Array 오브젝트 형태 : Array 메소드를 사용할 수 있습니다.
    • __proto__가 Array

분할할당(Destructuring)

let one, two, three;
const list = [1, 2, 3];
[one, two, three] = list;
console.log(one); 
console.log(two); 
console.log(three); 
console.log(list);
// 1
// 2
// 3
// [1,2,3]

사전적 의미로는 구조를 파괴한다는 의미가 있습니다. 하지만, 코드를 보면 원본 데이터가 파괴된다기보다는 구조분해 후 특정요소 pick을 한다는게 더 맞는 의미입니다.

즉, 파괴보다는 분할/분리에 더 가깝다고 볼 수 있고, "분할 할당"이라고 할 수 있습니다.

Array분할 할당

배열의 엘리먼트를 분할하여 할당할 수 있습니다.

  1. 인덱스에 해당하는 변수에 할당
    ⇒ 왼쪽의 인덱스에 해당하는 오른쪽 배열의 값을 할당합니다. one에 1, two에 2, three에 3이 할당됩니다.

    let one, two, three;
    [one, two, three] = [1, 2, 3];
    console.log(one);
    console.log(two);
    console.log(three);
    // 1
    // 2
    // 3
  2. 할당받을 변수 수가 적은 경우
    ⇒ 왼쪽에 할당받을 변수가 분할 할당할 값보다 적은 경우 왼쪽 인덱스에 맞추어 값을 할당합니다. 그렇기에 3은 할당되지 않습니다.

    let one, two;
    [one, two] = [1, 2, 3];
    console.log(one);
    console.log(two);
    // 1
    // 2
  3. 할당받을 변수 수가 많은 경우
    ⇒ 왼쪽의 할당받을 변수가 3개이고 분할 할당할 값이 2개라면 왼쪽에 값을 할당할 수 없는 변수에는 undefined가 설정됩니다.

    let one, two, three;
    [one, two, three] = [1, 2];
    console.log(two);
    console.log(three);
    // 2
    // undefined
  4. 배열 차원에 맞추어 분할 할당을 합니다.
    ⇒ [three, four]와 [3,4]가 배열이고 배열 차원도 변환됩니다.

    let one, two, three, four;
    [one, two, [three, four]] = [1,2,[3,4]];
    console.log([one, two, three, four]);
    // [1,2,3,4]
  5. 매치되는 인덱스에 변수가 없으면 값을 할당하지 않습니다.
    ⇒ [one, , , four] 형태에서 콤마로 구분하고 변수를 작성하지 않을 경우 인덱스를 건너 띄어 할당합니다.

    let one, two, three, four;
    [one, , , four] = [1,2,3,4];
    console.log([one, two, three, four]);
    // [1, undefined, undefined, 4]

spread와 병행 사용

  • 나머지를 전부 할당

    let one, rest;
    [one, ...rest] = [1,2,3,4];
    console.log(one); 
    console.log(rest);
    // 1
    // [2,3,4]
  • 인덱스를 반영한 나머지 할당

    let one, three, rest;
    [one, ,three ...rest] = [1,2,3,4, 5];
    console.log(three); 
    console.log(rest);
    // 3
    // [4, 5]

Object 분할 할당

Object의 프로퍼티를 분할하여 할당합니다.

  1. 프로퍼티 이름이 같은 프로퍼티에 값을 할당합니다.

    const {one, two} = {one: 10, two: 20};
    console.log(one);
    console.log(two);
    // 10
    // 20
  2. 프로퍼티 이름을 별도로 작성
    ⇒ 이처럼 프로퍼티 명을 위에 별도로 작성을 한 경우에 분할 할당을 하기위해서는 소괄호안에 작성을 하여 평가해야합니다.

    let one, two
    ({one, two} = {one: 10, two: 20});
    console.log(one);
    console.log(two);
    // 10
    // 20
  3. 프로퍼티 값 위치에 변수 이름 작성
    ⇒ 이름을 별도로 선언했기에 소괄호안에 작성합니다.
    one의 프로퍼티 값 5를 five에 할당하고, six도 마찬가지로 two의 프로퍼티 값인 6을 할당합니다.
    이때 one을 출력하려하면 ReferenceError가 발생합니다.(단지 분류의 기능 수행)

    let five, six;
    ({one: five, two: six} = {one: 5, two: 6});
    console.log(five);
    console.log(six);
    // console.log(one);  ---  ReferenceError
    // 5
    // 6
  4. Object구조에 맞춰 값 할당
    ⇒ 왼쪽의 할당받는 변수에서 plus: {two, three}에서 plus는 구조(경로)를 만들기 위해 존재하며 구조가 다르면 실행할 때 에러가 발생하기에 작성합니다. 그렇기에 plus는 실제로 존재하지 않습니다.

    const {one, plus: {two, three}} 
      = {one: 10, plus:{two:20, three:30}};
    console.log(one);
    console.log(two);
    console.log(three);
    // 10
    // 20
    // 30
  5. 나머지를 Object로 할당

    const {one, ...rest} = {one: 10, two: 20, three:30};
    console.log(rest);
    // {two: 20, three:30}

파라미터 분할 할당

  • 호출하는 함수에서 Object형태로 넘겨준 파라미터 값을 호출받는 함수의 파라미터에 맞추어 할당합니다.

    function add({one, two}) {
      console.log(one + two);
    }
    add({one: 10, two: 20});
    // 30

    ⇒ 호출하는 함수에서 넘겨준 one과 two가 담긴 오브젝트를 호출받는 함수의 프로퍼티 이름에 맞춰 분할 할당합니다.

  • Object구조에 맞춰 값을 할당합니다.
    function add({one, plus:{two}}) {
      console.log(one + two);
    }
    add({one: 10, plus:{two: 20}});
    // 30

Object 오퍼레이션

  • 같은 프로퍼티 이름 사용

    const value = {book: 10, book: 20};
    console.log(value);
    // 20
    • {book: 10, book: 20}에서 프로퍼티 이름(book)이 같습니다.
    • ES5 strict 모드에서 프로퍼티 이름이 같으면 에러가 발생합니다.
    • ES6에서는 strict 모드에 관계 없이 에러가 발생하지 않고 뒤에 작성한 프로퍼티 값으로 대체됩니다.
  • Shorthand property names

    const one = 10, two = 20;
    const values = {one, two};
    console.log(values);
    // {one: 10, two: 20}
    • one과 two변수에 값을 작성 후 {one, two} 형태로 value에 할당합니다.
    • 그렇게 되면 one, two는 프로퍼티 이름이되고 10, 20이 프로퍼티 값으로 할당이 됩니다.
    • 이것(Shorthand property names)은 MDN에 작성된 것으로 스펙에 정의된 것은 아닙니다.

프로퍼티 이름 조합

  • 문자열을 프로퍼티 이름으로 사용

    const value = { 
    ["one" + "two"]: 12 
    };
    console.log(value.onetwo);
    // 12

    ⇒ [ ]안에 문자열로 이름을 작성하면 그 문자열이 프로퍼티 이름이 되는데 우측 코드에서 one + two로 문자열 결합이 되어 onetwo가 프로퍼티 이름으로 사용됩니다.

  • 변수값을 프로퍼티 이름으로 사용

    const item = "world";
    const sports = {
      [item]: 100,
      [item + " Cup"]: "월드컵",
      [item + "Sports"]: function() {
        return "스포츠";
      }
    };
    console.log(sports[item]); // 100
    console.log(sports[item + " Cup"]); //월드컵
    console.log(sports[item + "Sports"]());// 스포츠
    // 100
    // 월드컵
    // 스포츠

    ⇒ 변수값을 프로퍼티 이름으로 사용합니다.
    ⇒ 변수값을 문자열 결합하여 사용할 수도 있습니다.
    ⇒ 프로퍼티 이름에 공백도 넣을 수 있습니다.
    ⇒ 함수로 호출할 수도 있습니다.

  • 분할 할당을 조합한 형태

    const item = "book";
    const result = {[item]: title} = {book: "책"};
    console.log(result);

    ⇒ 변수값을 프로퍼티 이름으로 사용하고 분할 할당하는 형태입니다.
    ⇒ {[item]: title}은 {book: title} 형태가 됩니다.
    ⇒ {book: title} = {book: "책"}이 되어 result는 {book: "책"}이 됩니다.


default value

값을 할당하지 않으면 사전에 정의된 값(default value)을 할당하는 것입니다.

  • 할당할 값이 없으면 디폴트 값을 할당합니다.

    const [one, two, five = 50] = [10, 20];
    console.log(five);
    // 50
    • one에는 10을, two에는 20을 분할 할당합니다.
    • 이때 five에는 할당할 값이 없지만, five = 50이기에 50을 할당합니다.
    • 이것을 default value라 합니다.
  • 할당할 값이 있으면 디폴트 값을 무시합니다.

    const [one, two, five = 50] = [10, 20, 70];
    console.log(five);
    // 70

    ⇒ 왼쪽과 오른쪽 모두 값이 3개로 할당 값도 할당 받을 변수도 맞기에 five는 50이 아닌 우측에서 70을 할당받습니다.

  • Object는 프로퍼티 이름으로 체크합니다.

    const {one, two = 20} = {one: 10};
    console.log(two);
    // 20

    ⇒ 우측의 one값인 10을 좌측의 one 프로퍼티 값으로 분할할당합니다. two에는 할당할 값이 없으며 기본값인 20을 할당합니다.

  • 디폴트 값 적용 순서(좌 → 우)

    const [one, two = one + 20, five = two + 50] = [10];
    console.log(two);
    console.log(five);
    // 30
    // 80
    • 우측의 one값인 10을 좌측의 one프로퍼티 값으로 분할 할당합니다.
    • 이 후 우측 two와 five는 값이 없기에 디폴트 값을 할당합니다.
    • two는 one이 10으로 할당되어 two + one + 20에서
      10+20이 되어 30이되고
    • five도 같은 방법으로 30 + 50이 되어 80이 디폴트 값으로 할당됩니다.

함수의 파라미터에 디폴트 값 적용

  • 넘겨받은 파라미터 값이 없으면 디폴트 값을 할당합니다

    const add = (ten, two = 20) => ten + two;
    const result = add(10);
    console.log(result);
    // 30
    • add를 호출하는 시점에서 10을 넘겨주기에 ten에는 10이 할당됩니다.
    • two는 할당된 값이 없기에 undefined가 할당되야하나, 기본값이 20이 있어 20이 할당됩니다.
  • 넘겨받은 파라미터 값이 있으면 디폴트 값을 무시합니다.

    const add = (ten, two = 20) => ten + two;
    const result = add(10, 50);
    console.log(result);
    // 60

    ⇒ add(10, 50)으로 두 번쨰 파라미터도 작성을 해주게 되면 호출받은 함수의 파라미터부분에서도 디폴트 값을 적용하지 않습니다

  • 호출한 함수의 파라미터 값이 undefined일 때

    const point = () => 20;
    const add (one, two = point()) => one + two);
    const result = add(10, undefined);
    console.log(result);
    // 30
    • add(10, undefined)에서 두 번째 파라미터 값이 undefined이지만 파라미터 값을 넘겨주지 않은 것과 같습니다.
    • point()함수를 호출해 반환된 값(20)을 디폴트 값으로 사용합니다.

좋은 웹페이지 즐겨찾기