728x90
반응형

11. 배열과 객체 좀 더 깊게 살펴보기

ECMAScript2015 + 기능 정리

매개변수 기본값 

지정 O


      
function hello(name, message) {
console.log(`${name}님, ${message}`)
}
hello("도레미", "반갑습니다.") // "도레미님, 반갑습니다."
hello("백두산") // "백두산님, undefined"

 

지정 X


      
function hello(name, message = "안녕하세요?") {
console.log(`${name}님, ${message}`)
}
hello("도레미", "반갑습니다.") // "도레미님, 반갑습니다."
hello("백두산") // "백두산님, 안녕하세요?"

전개구문

마침표 세 개(...)의 다양한 쓰임

  • 함수
    • 매개변수의 개수에 상관없이 매개변수를 하나의 변수로 받을 수 있음
  • 배열
    • 배열과 배열 연결
    • 배열의 값만 꺼내서 복사

      
// 함수
function addNum(...numbers) {
let sum = 0;
for (let number of numbers)
sum += number;
return sum;
}
console.log(addNum(1, 2)); // 3
console.log(addNum(1, 2, 3, 4, 5)); // 15

      
// 변수
// 1
let animal = ["bird", "cat"]
let fruits = ["apple", "banana", cherry"]
animal.concat(fruits)
[...animals, ...fruits]
// 2
let fruits = ["apple", "banana", cherry"]
let favorites = fruits
favorite[1] = "grape"
fruits // ["apple", "grape", cherry"]

객체의 프로퍼티

대괄호 표기법

 

계산된 프로퍼티 이름

 

프로퍼티 단축


객체에서 심벌키 사용하기

심벌(Symbol)

  • ECMAScript2015 이후에 추가된 새로운 원시 자료형
  • 한 번 정의하면 값을 변경할 수 없고 유일한 값을 찾음
  • 2명 이상의 개발자가 하나의 프로그램 개발: 변수나 프로퍼티 이름을 같게 만드는 실수 피할 수 있음

심벌 사용해 프로퍼티 정의하기

객체 만들면서 일부 정보를 드러내고 싶지 않을 때 심볼 사용

 

심벌키에 접근하기

  • 심벌키를 사용한 프로퍼티나 메서드에 접근 -> 대괄호 사용
  • 심벌키를 사용한 메서드를 실행 -> 대괄호의 오른쪽에 소괄호(()) 붙임

      
const id = Symbol("id)
const tel = Symbol("telephone number")
const member = {
name: "Kime",
age: 25,
[id]: 1235,
[tel]: function() {
alert(prompt("전화번호: "));
}
}

      
for (item in member) {
console.log(`${item} : ${memeber[item]}`)
}
// name: Kim
// age: 25

      
member[id] // 1235
member[tel]() // 프롬프트 창에 전화번호 입력 -> 알림 창에 표시

전역 심벌

Symbol.for() 메서드

  • 키를 인수로 받고 전역 심벌 레지스트리를 뒤져서 키에 해당하는 심벌 찾음
  • 레지스트리에 키에 맞는 심벌에 있으면 해당 심벌을 반환, 그렇지 않으면 새로운 심벌은 만들어서 반환

      
// 기본형
Symbol.for(키)
let tel = Symbol.for("tel") // 처음이므로 심벌 생성
let phone = Symbol.for("tel") // tel 키에 대한 심벌 이미 있으므로 가져와서 사용
tel === phone // true

 

Symbol.keyFor() 메서드

심벌값을 인수로 받아서 전역 심벌 레지스트리를 뒤져서 심벌값의 키를 찾음


      
// 기본형
Symbol.keyFor(심벌값)
let tel = Symbol.for("tel")
let phone = Symbol.for("tel")
tel === phone
Symbol.keyFor(phone) // "tel"

구조 분해 할당

  • 주어진 자료의 구조를 분해해서 변수에 할당하는 기능 
  • 디스트럭팅(destructing)
  • 배열이나 객체는 하나의 변수에 다양한 값 들어 있는데, 그중에서 일부만 꺼내 다른 변수로 할당할 수 있음

      
// ver1
let [apple, peach] = ["사과", "복숭아"]
// ver2
const fruits = ["사과", "복숭아"]
let [apple, peach] = fruits

일부 값만 분해 할당하기


      
let [spring, fall, ] = ["봄", "여름", "가을", "겨울"]
spring // "봄"
fall // "가을"

 

나머지 변수를 사용

  • 일부 값을 변수로 지정 -> 나머지 값을 묶어서 하나의 변수로 할당
    나머지 변수: 나머지 값을 묶어서 만든 변수
  • 나머지 변수 이름 앞에 ...를 붙이고, 나머지 변수에 할당하는 값은 마지막에 오는 값이어야 함

      
let [teacher, ...students] = ["Kim", "Lee", "Park", "Choi"]
teacher // "Kim"
students // ["Lee", "Park", "Choi"]

두 변수의 값 교환하기


      
// 일반적인 방법
let tmp;
tmp = x;
x = y;
y = tmp;
// 구조 분해
[x, y] = [y, x]

객체 구조 분해

프로퍼티 이름이나 메서드 이름을 변수 이름으로 사용

-> 객체에는 순서가 없기 때문에 키 이름과 변수 이름이 같아야 해당 키를 찾아서 값을 가져올 수 있음


      
// 1
const member = {name: "Kim", age: 25}
let {name, age} = member
// 2
let name, age
{name, age} = {name: "Kim", age: 25}
name // "Kim"
age // 25

중첩된 객체 구조 분해

변수의 이름을 객체의 프로퍼티 이름이 아닌 다른 이름으로 지정


      
cosnt member = {
name: "Kime",
age: 25
}
// name 프로퍼티 값 -> userName 변수에 할당
let {name: userName, age} = member
username // "Kim"

      
const student = {
name: "도레미",
score: {
history: 85,
science: 84
},
friends: ["Kim", "Lee", "Park"]
}
let {
name, // student.name 값
score: {
history, // studnet.score.history 값
science // student.score.science 값
},
friends: [f1, f2, f3] // friends 배열 구조 분해
} = student

배열을 변형하는 메서드

map() - 배열에 같은 함수 적용

각 배열 요소에 똑같은 함수를 실행한 후 그 결과를 새로운 배열로 반환하는 메서드


      
// 기본현
map(함수(값))
// ex. numbers 배열의 각 요소에 2를 곱해서 새로운 배열을 만든다면
let numbers = [1, 2, 3, 4, 5]
let newNumbers = numbers.map(number => number * 2);
newNumbers // [2, 4, 6, 8, 10]

      
// 기본형
map(함수(값, 인덱스))
map(함수(값, 인덱스, 배열))
let numbers = [1, 2, 3, 4, 5]
let newNumbers2 = numbers.map((number, index) => index + (number * 3))
newNumbers2 // [3, 7, 11, 15, 19]

filter() - 특정 조건으로 골라내기

특정 조건에 맞는 요소만 골라내는 메서드


      
// 기본형
filter(함수(값))
filter(함수(값, 인덱스))
filter(함수(값, 인덱스, 배열))

      
let scores = [90, 35, 64, 88, 45, 92]
ex. 여러 점수가 저장된 scores 배열에서 85점 이상만 골라서 highScores 배열
highScores = scores.filter(score => score >= 85) // [90, 88, 92]
ex. scores 배열에서 85점 이상의 값 찾으면서 인덱스도
let highScores2 = scores.filter((score, index) => {
if (score >= 85) {
console.log(`index: ${index}, score: ${score}`);
return score;
}
});

reduce() - 값 누적하기

  • 배열 요소에 차례로 함수를 실행하면서 결괏값을 하나로 누적하는 메서드
  • 초깃값 생략할 수 있음
    • 생략 -> 배열의 첫 번째 값을 초깃값으로 사용

      
// 기본형
reduce(함수(누산기, 현잿값, 인덱스, 원래 배열), 초깃값)
  1. 현잿값 = 초깃값 + 첫번째 배열 요소 실행한 값
  2. 현잿값 = 기존 현잿값 + 두번째 배열 요소 실행한 값
  3. ...

      
// ex. numbers 배열에 있는 요소를 차례대로 더해서 result에 저장
let numbers = [1, 2, 3, 4, 5]
let result = numbers.reduce((total, current) => total + current, 0);
result // 15

Map과 Set

여러 값을 하나의 변수로 묶어서 처리하기 위해 배열이나 객체 사용

But, 객체로는 부족

  • '키'에는 문자열만 사용 X
    • 맵에는 키에 모든 값 사용 O
  • 여러 정보를 담을 수 있지만, 프로퍼티 간 순서 X
    • 맵과 셋에는 순서 O
  • for 문과 같은 반복문을 사용해서 객체의 프로퍼티를 반복할 수 X
    • 맵과 셋에서는 for...of 같은 반복문 사용 O
  • 프로퍼티의 개수를 알려 주는 프로퍼티 X
    • 맵과 셋에는 별도의 프로퍼티 O
  • 맵과 셋은 배열이나 객체보다 많은 메서드 가지고 있음

맵(Map)

  • '키'와 '값'이 하나의 쌍으로 이루어졌고 여러 개의 프로퍼티를 가지고 있는 자료 형태 (객체와 비슷)
  • 맵의 프로퍼티키는 문자열뿐만 아니라 모든 자료형을 사용할 수 있음
    • 객체나 함수도 사용할 수 있음

맵의 프로퍼티는 순서대로 접근하고 처리할 수 있음


      
// 기본형
new Map() // Map 객체 만듦
set(키, 값) // Map 객체에 프로퍼티 추가
// ex.
let bag = new Map() // Map
bag.set("color", "red") // {"color" => "red"}

 

Map 객체를 만들면서 프로퍼티 지정할 수 있음


      
// 기본형
new Map() ([
[키1, 값1],
[키2, 값2],
...
]);
// ex.
let myCup = new Map ([
["color", "white"],
["haveHandle", true],
["matrial", "ceramic"],
["capacity", "300ml"]
])
myCup
// {"color" => "white", "haveHandle" => true, "material" => "ceramic", "capacity" => "300ml"}

 

맵 체이닝


      
bag.set("type", "mini").set("purpose", "daily")

 

=> 맵의 메서드는 맵을 반환


맵의 프로퍼티와 메서드


      
// 기본형
size // 맵 요소의 개수 알려주는 프로퍼티
set(키, 값) // 프로퍼티 추가를 추가
get(키) // 해당 키의 값 반환
has(키) // 해당 키가 맵에 있는지 체크하고 true/false 반환
delete(키) // 해당 키가 있는 프로퍼티 삭제
clear() // 맵의 모든 요소 삭제
// 키와 값을 가져오는 메서드
key() // 각 요소의 키를 모아서 반환
values() // 각 요소의 값을 모아서 반환
entries() // [키, 값] 형태로 모든 요소 반환

      
let myCup = new Map ([
["color", "white"],
["haveHandle", true],
["matrial", "ceramic"],
["capacity", "300ml"]
])
myCup.keys()
// MapIterator {"color", "haveHandle", "material", "capacity"}
for(let key of myCup.keys()) {
console.log(key)
}
  • 맵: 순서를 가지고 있는 객체 -> 이터러블 객체
  • 키나 값을 가져오는 메서드는 이터러블 객체 반환

셋(Set)

  • 배열: 키 없이 여러 개의 값을 모아 놓은 것/ 값이 중복되어도 상관 X
  • 셋: 키 없이 여러 개의 값을 모아 놓은 것(= 배열)/ 값 중복 X

Set 객체의 인스턴스 만든 후 값을 추가


      
// 기본형
new Set()
new Set(배열)
add(값)
// ex.
let numSet1 = new Set()
numSet1.add("one") // {"one"}
numSet1.add("two") // {"one", "two"}
// 체이닝해서 작성
let numSet1 = new Set().add("one").add("two")

 

배열을 인수로 받아서 셋으로 만들 수 있음


      
let numSet2 = new Set([1, 2, 3])
numSet2 // {1, 2, 3}
let numSet3 = new Set([1, 2, 1, 3, 1, 5])
numSet3 // {1, 2, 3, 5}

 

=> 중복 값이 있는 배열을 받아도 중복값을 모두 제거하고 셋을 만듦


셋의 프로퍼티와 메서드


      
// 기본형
size // 셋 요소의 개수 반환
add(값) // 셋에 값 추가
has(값) // 셋에 해당 값이 있는지 체크
delete(값) // 셋에서 해당 값을 삭제
clear() // 셋을 비움
// 이터러블 객체 반환
keys() // 셋에 있는 모든 값을 반환
values() // 셋에 있는 모든 값을 반환
entries() // [값, 값] 형식으로 모든 값 반환

      
let students = new Set();
students.add("도레미")
students.add("백두산")
students.add("도레미")
students // {"도레미", "백두산"}
students.key() // {'도레미', '백두산'}
students.values() // {'도레미', '백두산'}
students.entries() // {'도레미' => '도레미', '백두산' => '백두산'}

이터레이터와 제너레이터

이터러블 객체

  • 이터러블(iterable): 순서대로 처리할 수 있다
  • 문자열, 배열, 맵, 셋
    • ex. 배열: 인덱스와 값 -> 인덱스 0부터 차례대로 값을 가져와서 처리할 수 있음
  • 기능
    • for...of 반복문
    • 전개 연산자(...)
    • 구조 분해 할당

      
// ex. 문자열
let hi = "hello";
// for...of
for (let ch of hi) {
console.log(ch)
}
// 전개 연산자
let chArray = [...hi]
chArray // ["h", "e", "l", "l", "o"]
// 구조 분해 할당 사용
let [ch1, ch2] = hi
ch1 // "h"
ch2 // "e"

 

일반 객체는 이터러블 X

객체 안에 많은 자료를 저장하고 처리해야 함 -> 전개 연산자 or 구조 분해 할당 사용 or for...of문으로 순회하는 것이 편리

=> 일반 객체를 이터러블하게 만들어서 사용(제너레이터 함수 사용)


Symbol(Symbol.iterator): f values()

  • 이터러블 객체에는 Symbol.iterator 메서드가 포함: 이터러블 프로토콜
  • Symbol.iterator 메서드 실행 -> Iterator 객체 반환

Iterator 객체

  • 객체의 요소를 순서대로 꺼낼 수 있는 객체
  • next() 메서드가 있기 때문에 가능, valuedone 반환
    • value: 다음 값
    • done: 이터레이터 객체가 끝났는지 여부

제너레이터 함수

  • 일반 객체를 이터러블하게 만들기 위해 사용하는 함수
  • 일반 함수와 구별하기 위해 function 다음에 *기호 붙여서 작성
  • 함수 안에 return 문 대신에 yield 문 사용

      
// 함수 정의
function* 함수명() {
...
yield
}
// 객체 만들기
객채명 = 함수명()

      
// ex
function* gen() {
yield 1;
yield 2;
yield 3;
}
// next() 메서드
let g1 = gen()
g1.next() // {value: 1, done: false}
g1.next() // {value: 2, done: false}
g1.next() // {value: 3, done: false}
g1.next() // {value: undefined, done: true}
g1 // gen {<closed>}
// for...of
let g2 = gen()
for (let i of g2) console.log(i)
let g3 = gen()
g3.next() // {value: 1, done: false}
for(let i of g3) console.log(i)

출처

 

Do it! HTML+CSS+자바스크립트 웹 표준의 정석

 

www.youtube.com

728x90
반응형
김앩옹