자바스크립트 ES6 문법

디스트럭처링스프레드리터럴옵셔널 체이닝
avatar
2025.04.10
·
10 min read

디스트럭처링

디스트럭처링 할당이란?

구조화된 배열 또는 객체를 비구조화하여 1개 이상의 분수에 개별적으로 할당하는 것.

배열 디스트럭처링 할당

const food = ["라면", "스프", "계란"];

const [noodle, soup, topping, time = 3] = food;

console.log(noodle, soup, topping, time); // 라면 스프 계란 3
  • 순서에 의미가 있다.

  • 변수와 배열의 개수가 일치하지 않아도 된다.

  • 디스트럭처링을 사용하기 위해선 오른쪽에 반드시 배열이 있어야 한다. (단독 사용 불가)

  • 기본값을 설정할 수 있다.

객체 디스트럭처링 할당

const food = { noodle: "라면", soup: "스프", topping: "계란" };

const { noodle, soup, topping, time = 3 } = food;

console.log(food.noodle, food.soup, food.topping, time); // 튀긴면, 스프, 계란, 3

// 원본 프로퍼티key와 다른 이름으로 객체를 만들고 싶은 경우
const { noodle: noo, soup: sou, topping: topp, cooktime = 3 } = food;
console.log(noo, sou, topp, time); // 튀긴면, 스프, 계란, 3

// key값만 추출할 수 있다.
const { topping: toppp } = food;
console.log(toppp); // 계란

// 함수의 매개변수에도 사용할 수 있다.
function cook({ time, salty }) {
  console.log(`요리시간: ${time}분, 간: ${salty}`);
}

cook({ time: 3, salty: "삼삼하게" }); // 요리시간: 3분, 간: 삼삼하게
  • 배열 디스트럭처링과 달리 순서는 상관 없다.

  • 디스트럭처링을 사용하기 위해선 오른쪽에 반드시 객체가 있어야 한다. (단독 사용 불가)

  • 기본값을 설정할 수 있다.

  • key값만 추출할 수 있다.

  • 매개변수에도 사용할 수 있다.


배열 디스트럭처링과 객체 디스트럭처링의 혼용

const noodles = [
  { noodle: "튀긴면", soup: "스프", topping: "계란" },
  { noodle: "잔치국수면", soup: "멸치국물", topping: "계란지단" },
  { noodle: "냉면", soup: "소고기국물", topping: "계란" },
];

// todos 배열의 두번째 요소인 객체로부터 id 프로퍼티만을 추출한다.
const [, { noodle }] = noodles;
console.log(noodle); // 잔치국수면

// 중첩 객체 사용법
const user = {
  name: "Yu",
  address: {
    zipCode: "03068",
    city: "Seoul",
  },
};
const {
  address: { city },
} = user;
console.log(city); // 'Seoul'

배열과 객체 디스트럭팅을 함께 사용 가능하다.


스프레드

스프레드 문법이란?

하나로 뭉쳐 있는 여러 값들의 집합을 펼쳐서 개별적인 값들의 목록으로 만드는 것.

  • 값을 만드는게 아니기 때문에 변수에 할당할 수 없다.

  • 이터러블에 한정되어 사용될 수 있다.

  • 단독으로 사용될 수 없고 다음과 같이 사용될 수 있다.

    • 함수 호출문의 인수 목록

    • 배열 리터럴의 요소 목록

    • 객체 리터럴의 프로퍼티 목록 (최신버전)

함수 호출문의 인수 목록에서 사용하는 경우

const arr = [1, 2, 3];
const minValue = Math.min(...arr);
console.log(minValue);  // 1

Rest파라미터와는 다르다. Rest 파라미터는 여러개의 값을 동시에 받기 위해 사용한다.

function cook(param, ...rest) {
  // 레스트 파라미터
  console.log(param);  // 면
  console.log(rest);   // ['계란', '스프']
}

cook(...['면', '계란', '스프']);  // 스프레드 문법

배열 리터럴 내부에서 사용하는 경우

concat

var arr = [1, 2].conat([3, 4]);
console.log(arr);  // [1, 2, 3, 4]

const arrS = [...arr, 5, 6];
console.log(arrS);

push

var arr1 = [1, 2];
var arr2 = [3, 4];
const arr3 = [5, 6];

Array.prototype.push.apply(arr1, arr2);
console.log(arr1);  // [1, 2, 3, 4]

// 스프레드 문법
arr1.push(..arr3);
console.log(arr1);  // [1, 2, 3, 4, 5, 6]

splice

var arr1 = [1, 4];
var arr2 = [2 ,3];

// apply 메소드의 2번째 인수는 배열이다. 이것은 인수 목록으로 splice 메소드에 전달된다.
// [1, 0].concat(arr2) → [1, 0, 2, 3]
// arr1.splice(1, 0, 2, 3) → arr1[1]부터 0개의 요소를 제거하고
// 그자리(arr1[1])에 새로운 요소(2, 3)를 삽입한다.

Array.prototype.splice.apply(arr1, [1, 0].concat(arr2));

console.log(arr1); // [1, 2, 3, 4]

// 스프레드 문법
const arr1 = [1, 4];
const arr2 = [2, 3];

arr1.splice(1, 0, ...arr2);

console.log(arr1); // [1, 2, 3, 4]

slice (배열 복사)

var origin = ["면", "스프"];
var copy = origin.slice();

console.log(copy); // ['면', '스프']
console.log(copy === origin); // false

// 스프레드 문법
const origin2 = ["면", "멸치육수"];
const copy2 = [...origin2];

console.log(copy2); // ['면', '멸치육수']

유사 배열 객체를 배열로 변환

function isRamen() {
  var args = Array.prototype.slice.apply(arguments);

  return args.some((item) => item === "스프");
}

console.log(isRamen("면", "계란", "스프")); // true

// 스프레드 문법
function isRamen2() {
  var args = [...arguments];

  return args.some((item) => item === "스프");
}

console.log(isRamen2("면", "계란", "스프")); // true

객체 리터럴 내부에서 사용하는 경우

const merged = Object.assign({}, { x: 1, y: 2 }, { y: 10, z: 3 });
console.log(merged); // { x: 1, y: 10, z: 3 }

// 스프레드 문법
const merged2 = { ...{ x: 1, y: 2 }, ...{ y: 10, z: 3 } };
console.log(merged2); // { x: 1, y: 10, z: 3 }

옵셔널 체이닝

Optional Chaning (?.) 이란?

  • 프로퍼티가 없는 중첩 객체에서도 에러 없이 안전하게 접근할 수 있는 방법이다.

  • ?.의 앞 대상을 평가하여 undefined 또는 null을 반환하면 평가를 멈추고 undefined를 반환한다.

  • ?.의 앞 대상을 평가하여 undefined 또는 null을 반환하지 않으면 해당 프로퍼티에 정상적으로 접근가능하다.

예시

let user = {};  // 주소 정보가 없는 사용자
alert(user.address.name);
// TypeError: Cannot read property 'address' of undefined
alert(user.address?.name);
// undefined

user라는 빈 객체 생성 후 useraddress의 프로퍼티 내부의 name 을 출력할 때
address가 존재하지 않고, name 또한 존재하지 않는다.
이럴 때 에러를 반환하는데 ?.를 사용하여 프로퍼티 내부로 진입 시 에러 없이 undefined를 반환받을 수 있다.

옵셔널 체이닝을 사용할 때 주의!!

  • ?.는 존재하지 않아도 괜찮은 대상에만 사용해야한다.

  • 위 예시에서 논리상 user는 반드시 있어야 하는데 address는 필수값이 아니다.

  • 실수로 인해 user에 값을 할당하지 않았다면 바로 알아낼 수 있도록 해야한다. 그렇지 않으면 에러를 조기에 발견하지 못하고 디버깅이 어려워진다.

  • 변수 user가 선언되어있지 않으면 user?.anything 평가시 에러가 발생한다. (user?.anything을 사용하려면 let이나 const,var를 사용해서 user를 정의해야 한다.

  • 옵셔널 체이닝은 선언이 완료된 변수를 대상으로만 동작한다.

요약

  • Obj?.prop : Obj가 존재하면 Obj.prop을 반환하고, 그렇지 않으면 undefined를 반환

  • Obj?.[prop] : Obj가 존재하면 Obj[prop]을 반환하고, 그렇지 않으면 undefined를 반환

  • Obj?.method() : Obj가 존재하면 Obj.method()을 호출하고, 그렇지 않으면 undefined를 반환

  • ?. 왼쪽 평가 대상이 null이나 undefined인지 확인하고 null이나 undefined가 아니라면 평가를 계속 진행한다.

  • ?.를 계속 연결해서 체인을 만들면 중첩 프로퍼티들에 안전하게 접근할 수 있다.

  • ?.?.왼쪽 평가대상이 없어도 괜찮은 경우에만 선택적으로 사용해야 한다.







- 컬렉션 아티클