본문 바로가기
JS 공부

JS문법종합반 정리 2주차 - ES6문법, 일급객체로서 함수, Map, Set

by 나노다 2024. 11. 5.

구조 분해 할당 Destructuring

배열이나 객체의 속성들을 분해해서 각각의 값을 변수에 할당할 수 있게 해줌

/* 배열 분해 할당 */
let arr = ["1", "2", "3"];
let [a, b, c] = arr;

console.log(a, b, c); // 반환 : "1" "2" "3"

/* 객체 분해 할당 */
let obj = { name : "Bob", age : 25 };
let {name, age} = obj; 

console.log(name, age); // 반환 : "Bob" 25
  • 객체 분해 할당의 경우 변수명을 key 이름과 일치시켜야 하는데, 만약 변수 이름을 다르게 하고 싶다면 "key : 새이름"과 같이 설정해줄 수 있다
/* 이름 바꿔 분해 할당 */
let obj = { name : "Bob", age : 25 };
let {name : newName, age : newAge} = obj; 

console.log(name, age); // 참조 오류 : 선언되지 않은 변수!!
console.log(newName, newAge); // 반환 : "Bob" 25
  • 만약 할당할 변수 개수가 구조 속성 수보다 많은 경우, 짝이 없는 변수는 undefined가 됨. 이를 방지하기 위해선  "변수 = 초기값" 같은 방식으로 짝이 없을 경우 가질 값을 설정할 수 있음. 만약 초기값이 설정돼있는데 짝이 지어진다면, 초기값은 사라지고 구조의 속성 값이 새로 할당됨.
/* 배열 - 변수 수가 더 많은 경우 */
let arr = ["1", "2", "3"];
let [a, b, c, d] = arr;
console.log(d); // 반환 : undefined

/* 초기값 설정했고, 짝꿍이 없는 경우 */
[a, b, c, d = "4"] = arr;
console.log(a, b, c, d); // 반환 : "1" "2" "3" "4"

/* 초기값 설정했는데, 짝꿍이 있는 경우 */
arr = ["1", "2", "3", "5"];
[a, b, c, d = "4"] = arr;
console.log(a, b, c, d); // 반환 : "1" "2" "3" "5"


/* 객체 - 변수 수가 더 많은 경우 */
let obj = { name : "Bob", age : 25 };
let {name, age, gender} = obj; 
console.log(gender); // 반환 : undefined

/* 초기값 설정했고, 짝꿍이 없는 경우 */
({name, age, gender = "male"} = obj); 
console.log(name, age, gender); // 반환 : "Bob" 25 "male"

/* 초기값 설정했는데, 짝꿍이 있는 경우 */
obj = { name : "Bob", age : 25, gender : "female" };
({name, age, gender = "male"} = obj); 
console.log(name, age, gender); // 반환 : "Bob" 25 "female"

▼ 분해 할당을 다시 할 때, 배열은 상관 없지만 객체엔 할당 전체를 감싸는 소괄호가 필요한 이유?

더보기

 자바스크립트에선 중괄호로 감싼 부분을 컴퓨터가 만났을 때, 제일 먼저 코드블럭으로 인식함. 배열 관련으로 특정된 대괄호 []와 달리, 함수나 구문의 코드블럭으로도 쓰이고, 객체로도 쓰이는 중괄호 {}기 때문에, 혼동의 여지가 높아 의도대로 사용하려면 특정이 필요함.

 

위 예시에서 소괄호를 덮어줘야하는 이유는, 컴퓨터에게 중괄호 부분이 객체 리터럴임을 알려줘서 이 구문이 구조 분해 할당을 하는 중임을 명확히 하기 위함

 

단축 속성명 property shorthand

 

객체를 생성할 때, key와 value 값이 같다면 생략이 가능함

/* 단축 속성명 */
const obj = {
  name // name : name 과 같은 의미
  age : 25
};

 

 

전개 구문 추가 정보

 전개 구문 자체는 속성들을 객체나 배열에서 풀어내는 것임. 그래서 spread operator

/* spread 인 이유 */
let arr = ["1", "2", "3"];
let copied_arr = [...arr]; // 풀어진 속성들을 다시 배열 [] 안에 넣음

console.log(copied_arr); // 반환 : ["1", "2", "3"]
console.log(...arr); // 반환 : "1" "2" "3"

 

 

나머지 매개변수 rest parameter

 매개변수의 가짓수가 유동적일 경우, 전개 구문을 활용해 상황에 맞게 인자를 받을 수 있음

function func(a, b, c, ...arg) {
    console.log(a, b, c, ...arg); // 나머지 매개변수가 몇이든 풀어 써줌
    console.log(arg); // 전개구문 안 쓰면 나머지 매개변수를 다 담은 배열 하나 출력
}
func(1,2,3,4,5,6,7);
// 반환1 : 1 2 3 4 5 6 7
// 반환2 : [4, 5, 6, 7]

 

 

템플릿 리터럴 Template literals

문자열을 백틱으로 감싸 변수를 출력하는 등의 유동적인 활용이 가능한 기능.

추가로 알게 된 것은 줄바꿈도 적용해준다는 점!

console.log(`
    Dear John
    Nice to meet you!`) 

/* 반환 */
    Dear John
    Nice to meet you!

 

 

일급 객체로서의 함수

 자바스크립트에서 함수는 다른 객체들 처럼 일반적으로 적용 가능한 연산을 모두 지원함.

 함수를 매우 유연하게 활용할 수 있도록 해주는 특성으로, 일급 객체로 취급되는 5가지 경우가 있다

/* 함수의 일급 객체 특성 활용 */
function mulBy(num) {
    return function (x) {
        return x * num;
    }; // 함수를 반환하는 함수
}

function add(a, b) {
    return a + b;
}

const mulBy2 = mulBy(2); // 변수에 할당되는 함수
const mulby3 = mulBy(3);

console.log(mulBy2(10)); // 함수에서 반환된 함수에 매개변수 입력
console.log(mulby3(10));

const result = add(mulBy2(10), mulby3(10)); // 함수에서 반환된 함수의 반환값을 함수의 매개변수로
console.log(result);

 

 

일급객체인 함수 01 - 변수에 함수 할당

 함수 생성하는 방식 중 함수 표현식이 이에 해당! 변수에 함수를 저장해놓음으로써 함수를 재사용할 수 있게 됨

const sayHi = function() {
  console.log("Hi!");
};

sayHi(); // 반환 : "Hi!"

 

 

일급객체인 함수 02 - 함수를 인자로 다른 함수에 전달

 관련 개념으로 콜백함수와 고차함수가 있음

  • 콜백함수 : 어떤 함수의 매개변수로 들어가는 함수
  • 고차함수 : 함수를 인자로 받거나, 반환 값이 함수인 함수
function call_function(func) {
  func();
}

const sayHi = function() {
  console.log("Hi!");
};

call_function(sayHi); // 인자로 들어갈 땐 소괄호 () 붙이지 않음

 

 

일급객체인 함수 03 - 함수에서 함수를 반환

 함수 팩토리나 클로져를 작성할 때 사용

function func_add (num) {
    return function(x) {
        return x + num;
    }
}
const addFive = func_add(5);

console.log(addFive); // 반환 : [Function (anonymous)], 함수인 function(x) { return x + 5 }가 반환된 것
console.log(addFive(10)); // 반환 : 15, 위에 반환된 함수에 인자로 10이 들어가 최종 결과가 나옴

 

 

일급객체인 함수 04 - 객체의 프로퍼티로 함수 할당

 key가 일종의 함수명, value가 함수의 내용과 같은 느낌

 객체의 value에 접근하는 방식과 동일하게 "객체이름.key이름"으로 함수 내용에 접근할 수 있음

const person = {
    name : "Bob",
    age : 25,
    isMarried : true,
    sayHI : function () {
        console.log(`Hi, My name is ${this.name}.`);
    }, // this.name은 person.name과 같은 의미지만 person의 내부에서 쓰기 때문에 this로
    sayHello : () => {console.log(`I'm ${this.age} years old.`)}
    // 화살표 함수는 this를 바인딩하지 않는다!! 그래서 undefined 나옴
}

/* 객체의 프로퍼티인 함수에 접근 */
person.sayHI(); // 반환 : "Hi, My name is Bob"
person.sayHello(); // 반환 : undefined

 

 

일급객체인 함수 05 - 배열의 요소로 함수 할당

일반적인 배열에 접근하듯 인덱스를 활용해 배열 내 함수에 접근할 수 있음

const myArr = [
    function(a, b) {
        return a + b;
    },
    function(a, b) {
        return a - b;
    }
]

/* 배열 요소인 함수에 접근 */
console.log(myArr[0](1,3));
console.log(myArr[1](5,3));

 

 

자료구조 01 - Map

  • 객체와 유사한 자료구조로,  key와 value 쌍의 형태로 값을 저장함.
  • key에 문자열이 와야하는 객체와 달리 모든 타입이 위치할 수 있고,  추가된 순서로 저장되는 객체와 달리 정렬된 순서로 저장됨
  • key 값은 중복되지 않기 때문에, 동일한 key를 가진 value가 추가되면 기존 값에 덮어씌워짐
  • 반환하면 "Map(값의 개수) { key1 => value1, key2 => value2, ~}"의 형태

 

Map을 만들고 Map에 값을 추가하는 방법

/* Map 생성 */
const 맵이름 = new Map();

/* Map에 값 추가 */
맵이름.set(key, value);

/* 예시 */
const myMap = new Map();
myMap.set("a", 1);
myMap.set("b", 2);
myMap.set("b", 3); // "b"의 value는 3으로 덮어씌워짐
myMap.set("c", 4);

console.log(myMap); // 반환 : Map(3) { 'a' => 1, 'b' => 3, 'c' => 4 }

 

 

Map에서 value 값을 꺼내오는 방법

/* 기본 구조 */
맵이름.get(key이름) // key에 해당하는 value 반환. 존재하지 않는 key라면 undefined 반환

/* 예시 */
const myMap = new Map();
myMap.set("a", 1);
myMap.set("b", 2);

console.log(myMap.get("a")); // 반환 : 1
console.log(myMap.get("c")); // 반환 : undefined

 

 

어떤 key 값이 존재하는지 확인하는 방법

/* 기본 구조 */
맵이름.has(key이름) // 존재하는 key라면 true 반환. 존재하지 않는 key라면 false 반환

/* 예시 */
const myMap = new Map();
myMap.set("a", 1);
myMap.set("b", 2);

console.log(myMap.has("a")); // 반환 : true
console.log(myMap.has("c")); // 반환 : false

 

 

Map의 값을 제거하는 방법

 특정 key에 해당하는 값만 제거하고 싶다면 delete()를, 모든 값을 제거하고 싶다면 clear()를 활용

const myMap = new Map();
myMap.set("a", 1);
myMap.set("b", 2);
myMap.set("c", 3);
console.log(myMap); // 반환 : Map(3) { "a" => 1, "b" => 2, "c" => 3}

/* delete() 활용 */
myMap.delete("b");
console.log(myMap); // 반환 : Map(2) { "a" => 1, "c" => 3}

/* clear() 활용 */
myMap.clear();
console.log(myMap); // 반환 : Map(0) {}

 

 

Map이 가진 값의 개수를 반환하는 법 (Map의 길이 확인)

/* 기본 구조 */
맵이름.size

/* 예시 */
const myMap = new Map();
myMap.set("a", 1);
myMap.set("b", 2);

console.log(myMap.size); // 반환 : 2

 

 

Map의 반복

  • keys() : Map의 key 값들을 불러오는 메서드
  • values() : Map의 value 값들을 불러오는 메서드
  • entries() : Map의 프로퍼티들을 2차원 배열같은 느낌으로 불러오는 메서드
const myMap = new Map();
myMap.set("a", 1);
myMap.set("b", 2);
myMap.set("c", 3);

/* keys() */
console.log(myMap.keys()); // 반환 : [Map Iterator] { 'a', 'b', 'c' }

/* values() */
console.log(myMap.values()); // 반환 : [Map Iterator] { 1, 2, 3 }

/* entries() */
console.log(myMap.entries()); // 반환 : [Map Entries] { [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] }

 

 

자료구조 02 - Set

  • 배열과 유사한 형태의 자료구조로, Map과 달리 key를 필요로하지 않음
  • value간 중복이 없기 때문에 같은 값을 추가하면 기존 값에 덮어씌워져 Set의 길이가 변하지 않음
  • 반환하면 "Set (요소의 개수) { value1, value2, ~ }" 의 형태

 

Set을 만들고 Set에 값을 추가하는 방법

/* Set 생성 */
const 세트이름 = new Set();

/* Set에 값 추가 */
세트이름.add(value);

/* 예시 */
const mySet = new Set();
mySet.add("a");
mySet.add("b");
mySet.add("b"); // "b"는 이미 있으므로 덮어씌워짐
mySet.add("c");

console.log(mySet); // 반환 : Set(3) { 'a', 'b', 'c' }

 

 

Set에서 value 값을 꺼내오는 방법

Set는 각각의 요소 관리를 위하기 보단 요소들의 집합을 관리하기 위한 자료 구조기 때문에, 자체적으로 특정 요소를 반환하는 방법은 일단 없음. 정 필요하면 Set을 배열로 변환 후에 그 배열의 인덱스를 통해 값에 접근할 수 있음

const mySet = new Set();
mySet.add("a");
mySet.add("b");
mySet.add("c");

console.log(mySet[1]); // 반환 : undefined, Set 자체로는 접근 불가
console.log([...mySet][0]); // 반환 : "a", 배열로 변환해 접근 가능

 

 

Set에서 특정 value 값이 존재하는지 확인하는 방법

 Map과 마찬가지로 has()를 통해 확인하고, 값이 있으면 true, 없으면 false를 반환함

/* 기본 구조 */
세트이름.has(value)

/* 예시 */
const mySet = new Set();
mySet.add("a");
mySet.add("b");
mySet.add("c");

console.log(mySet.has("a")); // 반환 : true
console.log(mySet.has("d")); // 반환 : false

 

 

Set의 값을 제거하는 방법

 Map과 마찬가지로 특정 값만 제거하고 싶다면 delete()를, 모든 값을 제거하고 싶다면 clear()를 활용

/* 기본 구조 */
세트이름.delete(value)
세트이름.clear()

/* 예시 */
const mySet = new Set();
mySet.add("a");
mySet.add("b");
mySet.add("c");

mySet.delete("b");
console.log(mySet); // 반환 : Set(2) {"a", "c"}

mySet.clear();
console.log(mySet); // 반환 : Set(0) {}

 

 

Set가 가진 값의 개수를 반환하는 법 (Set의 길이 확인)

/* 기본 구조 */
세트이름.size

/* 예시 */
const mySet = new Set();
mySet.add("a");
mySet.add("b");
mySet.add("c");

console.log(mySet.size); // 반환 : 3

 

 

Set의 반복

 Map과 달리 Set는 key가 없기 때문에, values()만 적용 가능함

const mySet = new Set();
mySet.add("a");
mySet.add("b");
mySet.add("c");

console.log(mySet.values()); // 반환 : [Set Iterator] { 'a', 'b', 'c' }