4월2일) 큐빅레이스 스터디그룹

이병관·2022년 4월 1일
0

Destructing

구조 분해 할당이란?

MDN 정의에 따르면 배열이나 객체의 속성을 해체하여
그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식

배열(array)에서의 구조 분해 할당

let [a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

구조 분해 할당이라고 해서 특별한 문법적 형태가 다른 것이 아니라,
위처럼 할당받을 변수를 왼쪽에, 분해할 대상을 오른쪽에 해서 대입하는 형식으로 작성하면 됩니다.

배열 [10, 20] 이 분해되어 각각 a, b에 담긴 것입니다.

물론 아래와 같이 미리 저장해 둔 배열로부터 구조 분해 할당하는 형태도 당연히 가능합니다.

let array = [1, 2, 3];
let [a, b, c] = array;
console.log(a, b, c); // 1 2 3

여기서 또 활용되는 것이 앞의 포스팅에서 많이 보았던 ... 표현입니다.

이번 구조 분해 할당에서는 어떻게 쓰이는지 살펴보자면…

let array = [1, 2, 3, 4, 5];
let [a, b, ...rest] = array;
console.log(rest); // [3, 4, 5];

구조 분해 할당에서는 a, b 까지 1과 2가 대입이 되고,
나머지 3, 4, 5는 ...rest 로 받아서 [3, 4, 5] 와 같이 rest 변수에 배열로 저장해 줍니다.

참고로 배열 구조분해 할당(array destructuring assignment)에서 위와 같이 쓰이는 ... 요소를
Rest elements 라고 부릅니다. (참고 : https://v8.dev/features/object-rest-spread)

... 문법의 역할이 Rest 일 때, 파라미터에서 쓰이면 Rest 파라미터,
위처럼 배열의 구조분해 할당에 쓰일 경우 Rest elements가 됩니다.


객체(object)에서의 구조 분해 할당

객체에서의 구조 분해 할당은 아주아주 많이 쓰이는 문법입니다.
객체 내부의 프로퍼티 값을 간편하게 분해해서 변수에 저장할 수 있게 해 줍니다.

배열에서의 구조 분해 할당과 쓰이는 의미는 동일하되,
쓰이는 대상이 객체로 바뀐 것 뿐입니다.

단, 분해되는 대상이 배열은 arrayvalue(element) 였다면,
객체는 분해되는 대상이 객체의 property 인 차이가 있습니다.

const obj = {
  name: "John",
  age: 18,
  memo: "Hello",
};
const { name, age, memo } = obj;
console.log(name); // "John"
console.log(age); // 18
console.log(memo); // "Hello"

// 만약 구조 분해 할당을 사용하지 않는다면?
// 아래와 같이 직접 대입해 주어야 한다...
const name = obj.name;
const age = obj.age;
const memo = obj.memo;

const obj = {
  name: "John",
  age: 18,
  memo: "Hello",
};
const { name: YourName, age, memo } = obj;
console.log(YourName); // 'John'

객체 구조 분해 할당은 프로퍼티를 기준으로 하기 때문에,
배열 구조 분해 할당과 달리 그 순서가 뒤바뀌어도 전혀 문제없이 해당 프로퍼티의 값을 가져올 수 있습니다.

const obj = {
  name: "John",
  age: 18,
  memo: "Hello",
};
// memo, name, age 순으로 작성해도 상관이 없다. 알아서 해당 프로퍼티명에 해당하는 값을 저장한다.
const { memo, name, age } = obj;
console.log(name); // 'John'
console.log(age); // 18
console.log(memo); // 'Hello'

Map / Set

Map

  • Map() 은 자바스크립트의 key-value 페어(pair) 로 이루어진 컬렉션
  • key 를 사용해서 value 를 get, set 할 수 있음
  • key 들은 중복될 수 없음: 하나의 key 에는 하나의 value 만
  • key 로 사용할 수 있는 데이터형: string, symbol(ES6), object, function >> number 는 사용할 수 없음에 주의!
// 새로운 map 을 만들고 map 에 key, value 엔트리를 추가
let me = new Map();
me.set('name', 'kevin');
me.set('age', 28);
console.log(me.get('age'); // 28
// 대괄호를 사용해서 map 을 선언하는 방법
const roomTypeMap = new Map(
  [
    ["01", "원룸(오픈형)"],
    ["02", "원룸(분리형)"],
    ["03", "원룸(복층형)"],
    ["04", "투룸"],
    ["05", "쓰리룸"]
  ]
);
// 새로운 map 을 만들고 그 데이터를 기존의 [key, value] 페어컬렉션으로 채움
let you = new Map().set('name', 'paul').set('age', 34);
console.log(you.get('name')); // 'paul'
// has(): 주어진 key 가 존재하는지 확인
console.log(me.has('name')); // true
// size: map 에 담겨진 엔트리의 개수를 조회
console.log(you.size); // 2
// delete(): 엔트리를 삭제
me.delete('age');
console.log(me.has('age')); // false
// clear(): 모든 엔트리를 삭제
you.clear();
console.log(you.size); // 0

SET

  • Set() 은 value 들로 이루어진 컬렉션(“집합”이라는 표현이 적절)
  • Array 와는 다르게 Set 은 같은 value 를 2번 포함할 수 없음
  • 따라서 Set 에 이미 존재하는 값을 추가하려고 하면 아무 일도 없음
// 비어있는 새로운 set 을 만듬
let setA = new Set();
// 새로운 set 을 만들고 인자로 전달된 iterable 로 인자를 채움
let setB = new Set().add('a').add('b');
setB.add('c');
console.log(setB.size); // 3
// has(): 주어진 값이 set 안에 존재할 경우, true 를 반환
// indexOf() 보다 빠름. 단, index 가 없음
console.log(setB.has('b')); // true
// set 에서 주어진 값을 제거
setB.delete('b');
console.log(setB.has('b')); // false
// set 안의 모든 데이터를 제거
setB.clear();
console.log(setB.size); // 0

Class

ES2015에서 도입된 클래스는 생성자의 기능을 대체합니다.
class 표현식을 사용하면,
생성자와 같은 기능을 하는 함수를 훨씬 더 깔끔한 문법으로 정의할 수 있습니다.

class Person { } 
let kim = new Person(); 
console.log(kim); //person:{}

클래스는 다음과 같이 선언 할수 있으며 생성자Constructor를 사용해 초기값을 설정할 수 있습니다.

class Human { //인터페이스와 유사, 타입스크립트에선 클래스의 속성과 권한을 적어줘야함.
   public name: string;
   public age: number;
   public gender: string;
   constructor(name: string, age: number, gender: string){//생성자. 
     //메소드로써 클래스가 시작할때마다 호출. 클래스로부터 객체를 만들때.
      this.name = name;
      this.age = age;
      this.gender = gender;
   }
}
  • 클래스는 함수로 호출될 수 없습니다.
  • 클래스 선언은 let과 const처럼 블록 스코프에 선언되며, 호이스팅(hoisting)이 일어나지 않습니다.
  • 클래스의 메소드 안에서 super 키워드를 사용할 수 있습니다.

클래스 상속 (Class Inheritance)

클래스 상속(class inheritance, subclassing) 기능을 통해 한 클래스의 기능을 다른 클래스에서 재사용할 수 있습니다.

class Parent {
  // ...
}

class Child extends Parent {
  // ...
}

위 코드에서, extends 키워드를 통해 Child 클래스가 Parent 클래스를 상속했습니다.
이 관계를 보고 '부모 클래스-자식 클래스 관계' 혹은 '슈퍼 클래스(superclass)-서브 클래스(subclass) 관계'라고 말하기도 합니다.

어떤 클래스 A가 다른 클래스 B를 상속받으면, 다음과 같은 일들이 가능해집니다.

  • 자식 클래스 A를 통해 부모 클래스 B의 정적 메소드와 정적 속성을 사용할 수 있습니다.
  • 부모 클래스 B의 인스턴스 메소드와 인스턴스 속성을 자식 클래스 A의 인스턴스에서 사용할 수 있습니다.

super

앞서 봤듯이, 자식 클래스에서 부모 클래스의 정적 속성과 인스턴스 속성에 접근할 수 있었습니다.
하지만, 자식 클래스에 같은 이름의 속성을 정의한 경우 문제가 생깁니다.

class Melon {
  getColor() {
    return '제 색깔은 초록색입니다.';
  }
}

class WaterMelon extends Melon {
  getColor() {
    return '속은 빨강색입니다.';
  }
}

const waterMelon = new WaterMelon();
waterMelon.getColor(); // 속은 빨강색입니다.

이런 경우에, super 키워드를 통해 부모 클래스의 메소드에 직접 접근할 수 있습니다.

class Melon {
  getColor() {
    return '제 색깔은 초록색입니다.';
  }
}

class WaterMelon extends Melon {
  getColor() {
    return super.getColor() + ' 하지만 속은 빨강색입니다.';
  }
}

const waterMelon = new WaterMelon();
waterMelon.getColor(); // 제 색깔은 초록색입니다. 하지만 속은 빨강색입니다.

super 키워드의 동작 방식은 다음과 같습니다.

  • 생성자 내부에서 super를 함수처럼 호출하면, 부모 클래스의 생성자가 호출됩니다.
  • 정적 메소드 내부에서는 super.prop과 같이 써서 부모 클래스의 prop 정적 속성에 접근할 수 있습니다.
  • 인스턴스 메소드 내부에서는 super.prop과 같이 써서 부모 클래스의 prop 인스턴스 속성에 접근할 수 있습니다.
profile
뜨겁고 매콤하고 화끈하게

0개의 댓글