[JS] 9. Collection
in JS
1. 생성자
생성자 함수
// 빵틀
function FishBread(flavor, price){
this.flavor = flavor
this.price = price
this.base = "flour"
}
// 붕어빵
let bread1 = new FishBread("cream", 1200)
console.log(bread1)
//FishBread { flavor: 'cream', price: 1200, base: 'flour' }
let bread2 = new FishBread("milk", 2000)
console.log(bread2)
//FishBread { flavor: 'milk', price: 2000, base: 'flour' }
let bread3 = new FishBread("redBean", 800)
console.log(bread3)
//FishBread { flavor: 'redBean', price: 800, base: 'flour' }
- 유사한 객체를 다중으로 만들 때 사용되는 함수 (타 언어에서의 class 개념과 유사)
- 일반적으로 생성자 함수의 첫 글자는 대문자로 시작
- 생성자 함수로 객체 생성 시 new 연산자를 통해 객체 생성
- 생성자 함수와 new 연산자를 통해 빠른 객체 생성 가능
new.target
function User(name){
console.log(new.target)
if (!new.target) {
return new User(name)
}
this.name = name;
}
// 객체를 만들 때 new 를 썼는지 안썼는지 파악 가능
let result1 = User("John")
// undefined
console.log(result1)
// undefined
let result2 = new User("John")
//[Function: User]
console.log(result2)
//User { name: 'John' }
new.target
속성 (property)을 사용하여 new와 함께 호출했는지 확인 가능- 유연한 생성자 함수를 만들기 위해
new.target
이 없을 때,new
키워드 추가하여 호출되도록 처리
2. Collection
- 구조 혹은 비구조화 형태로 프로그래밍 언어가 제공하는 값을 담을 수 있는 공간
- 내부적으로 이터레이터가 있다 (반복문)
- js 에서 제공하는 collection
- Indexed Collection : Array, Typed Array
- Keyed Collection : Object, Map, Weak Map, Set, Weak Set
3. Map
- 다양한 자료형의 key를 허용하고, key-value 형태의 자료형을 저장 가능할 수 있는 Collection
- Map은 Object 대비 비교하면 다양한 key의 사용을 허용하고, 값의 추가/삭제 시 메서드를 통해 수행이 필요하다
- 생성자 :
new Map()
- 갯수 확인 :
Map.size
- 요소 추가 :
Map.set(key, value)
- 요소 접근 :
Map.get(key, value)
- 요소 삭제 :
Map.delete(key)
- 전체 삭제 :
Map.claer()
- 요소 존재 여부 확인 :
Map.has(key)
- 그 밖의 메서드 :
Map.keys()
,Map.values()
,Map.entires()
요소 추가/삭제
let map = new Map()
map.set("name", "John")
console.log(map)
//Map(1) { 'name' => 'John' }
map.set("123", "456")
console.log(map)
//Map(2) { 'name' => 'John', '123' => '456' }
map.set(true, "bool_type")
console.log(map)
//Map(3) { 'name' => 'John', '123' => '456', true => 'bool_type' }
console.log(map.get("123")) //456
console.log(map.get("name")) //John
console.log(map.get(true)) //bool_type
console.log(map.size) //3
map.delete("123")
console.log(map)
//Map(2) { 'name' => 'John', true => 'bool_type' }
map.clear()
console.log(map)
//Map(0) {}
map.set(123, 789).set(false, "bool_type").set("fruit", "banana")
console.log(map)
//Map(3) { 123 => 789, false => 'bool_type', 'fruit' => 'banana' }
- 요소 추가 :
Map.set(key, value)
- 요소 접근 :
Map.get(key, value)
- 전체 삭제 :
Map.claer()
- 다양한 자료형을 key로 사용 가능하며, map.set 호출 시 map 이 반환되므로 체이닝(chaining) 가능
Map 반복문
let recipe_juice = new Map([
["strawberry", 50],
["banana", 100],
["ice", 150],
]);
for (let item of recipe_juice.keys()) {
console.log(item);
// strawberry;
// banana;
// ice;
}
for (let amount of recipe_juice.values()) {
console.log(amount);
// 50;
// 100;
// 150;
}
for (let entity of recipe_juice) {
console.log(entity);
// ["strawberry", 50][("banana", 100)][("ice", 150)];
}
- Collection 객체인 Map이 가지고 있는 iterator 속성을 이용하여
for...of
구문을 통해 반복문 수행 가능
Map <> Object 변환
let recipe_juice = new Map([
["strawberry", 50],
["banana", 100],
["ice", 150],
]);
console.log(recipe_juice)
//Map(3) { 'strawberry' => 50, 'banana' => 100, 'ice' => 150 }
let recipe_juice_obj = Object.fromEntries(recipe_juice)
console.log(recipe_juice_obj)
//{ strawberry: 50, banana: 100, ice: 150 }
let recipe_juice_kv = Object.entries(recipe_juice_obj)
console.log(recipe_juice_kv)
// [ [ 'strawberry', 50 ], [ 'banana', 100 ], [ 'ice', 150 ] ]
let recipe_juice_map = new Map(recipe_juice_kv)
console.log(recipe_juice_map)
//Map(3) { 'strawberry' => 50, 'banana' => 100, 'ice' => 150 }
Object.entries(Object)
,Object.fromEntries(Map)
을 통해 Map과 Object 간 변환이 가능
Set
- value 만을 저장하며
중복을 허용하지 않는
Collection - 생성자 :
new Set()
- 갯수 확인 :
Set.size
- 요소 추가 :
Set.add(value)
- 요소 삭제 :
Set.delete(value)
- 전체 삭제 :
Set.claer()
- 요소 존재 여부 확인 :
Set.has(key)
- 그 밖의 메서드 :
Set.keys()
,Set.values()
,Set.entries()
요소 추가/삭제
let set = new Set()
let num = new Set([1, 2, 3, 4, 5])
let str = new Set("Hello!")
console.log(set) //Set(0) {}
console.log(num) //Set(5) { 1, 2, 3, 4, 5 }
console.log(str) //Set(5) { 'H', 'e', 'l', 'o', '!' }
set.add(1).add(2).add(10).add(10)
console.log(set) //Set(3) { 1, 2, 10 }
console.log(set.has(10)) //true
console.log(set.has(100)) //false
console.log(set.delete(100)) //false
console.log(set.delete(10)) //true
console.log(set) //Set(2) { 1, 2 }
- 요소 추가 :
Set.add(value)
- 요소 존재 여부 확인 :
Set.has(key)
- 요소 삭제 :
Set.delete(value)
- 다양한 자료형을 value로 사용 가능하며,
set.add
호출 시 set이 반환되므로 체이닝(chaining) 가능
Set 반복문
let str = new Set("Hello!");
console.log(str);
//Set(5) { 'H', 'e', 'l', 'o', '!' }
for (let item of str) {
console.log(item);
// H
// e
// l
// o
// !
}
// key 와 value 가 없기 때문에 안쓴것과 동일하다
for (let item of str.keys()) {
console.log(item);
// H
// e
// l
// o
// !
}
for (let item of str.values()) {
console.log(item);
// H
// e
// l
// o
// !
}
for (let item of str.entries()) {
console.log(item);
// [ 'H', 'H' ]
// [ 'e', 'e' ]
// [ 'l', 'l' ]
// [ 'o', 'o' ]
// [ '!', '!' ]
// Map 과의 포맷을 지키기 위해 해당 형태로 반환한다.
}
- Collection 객체인 Set 이 가지고 있는 iterator 속성을 이용하여
for...of
구문을 통해 반복문 수행 가능
5. Math
- 표준 Built-in 객체로서 수학적인 연산을 취한 속성값과 메서드를 제공하는 객체
- Math는 생서자 함수가 아니며, 모든 속성과 메서드는 정적이기에 Math.function()으로 언제든 호출 가능
- 오일러 상수(e) :
Math.E
- PI :
Math.PI
- 절대값:
Math.abs(x)
- 최대값 :
Math.max(...x)
- 최소값 :
Math.min(...x)
- 랜덤 난수 값 :
Math.random()
- 제곱과 제곱근 :
Math.pow(x,y)
,Math.sqrt(x)
- 소수점 처리 :
Math.round(x)
,Math.ceil(x)
,Math.floor(x)
최대/최소/절대값
console.log(Math.max(1, -1, 6, 8, 10, 12)); //12
console.log(Math.min(1, -1, 6, 8, 10, 12)); //-1
let nums = [1, -1, 6, 8, 10, 12]
console.log(Math.max.apply(null, nums)) //12
console.log(Math.min.apply(null, nums)) //-1
console.log(Math.max(...nums)) //12
console.log(Math.min(...nums)) //-2
console.log(Math.abs(-2)) //2
console.log(Math.abs(2)) //2
console.log(Math.abs(-Infinity)) //Infinity
- 배열을 인수로 받아 최대/최소를 산출하려면 apply 함수 혹은 스프레드 문법 사용 필요
속성 및 랜덤
// property
console.log(Math.E) //2.718281828459045
console.log(Math.PI) //3.141592653589793
// random 값의 범위를 다양하게 표현 가능
console.log(()) //0.6255519540470105
console.log(Number.parseInt(Math.random() * 10)) //6
console.log(Number.parseInt(Math.random() * 100)) //62
- 0과 1 사이의 난수 랜덤 값 :
Math.random()
제곱/제곱근/소수점 처리
// 제곱
console.log(Math.pow(2,3)) //8
console.log(2 ** 3) //8
// 제곱근
console.log(Math.sqrt(4)) //2
console.log(Math.sqrt(2)) //1.4142135623730951
// 반올림
console.log(Math.round(3.5)) //4
console.log(Math.round(-2.7)) //-3
console.log(Math.round(-2.3)) //-2
// 올림
console.log(Math.ceil(3.5)) //4
console.log(Math.ceil(-2.7)) //-2
console.log(Math.ceil(-2.3)) //-2
// 내림
console.log(Math.floor(3.5)) //3
console.log(Math.floor(-2.7)) //-3
console.log(Math.floor(-2.3)) //-3
- 제곱 :
Math.pow(x,y)
- 제곱근 :
Math.sqrt(x)
- 소수점 이하 반올림 정수 :
Math.round(x)
- 소수점 이하 올림 :
Math.ceil(x)
- 소수점 이하 내림 :
Math.floor(x)
6. Date
- 표준 Built-in 객체로서 날짜와 시간을 위한 속성값과 메서드를 제공하는 객체
- Date 객체는 1970년 1월 1일 UTC(협정 세계시) 자정과의 시간 차이를 밀리초로 나타내는 정수 값으로 표현
- Date 객체 생성자 :
new Date()
- 현재 시간 기준 문자열 :
Date()
- 날짜 정보 얻기 (년/월/일) :
Date.getFullYear()
,Date.getMonth()
,Date.getDate()
- 날짜 정보 얻기 (시/분/초/ms) :
Date.getHours()
,Date.getMinutes()
,Date.getSeconds()
- 날짜 정보 설정 (년/월/일) :
Date.setFullYear()
,Date.setMonth()
,Date.setDate()
- 날짜 정보 설정 (시/분/초/ms) :
Date.setHours()
,Date.setMinutes()
,Date.setSeconds()
- 그 외 날짜 정보 얻기 :
Date.getDay()
,Date.getTime()
,Date.getTimezoneOffset()
- 그 외 날짜 정보 설정 :
Date.parse(string)
Date 생성자 종류
let date_now = new Date()
let date_str = Date()
console.log(date_now) //2021-09-28T03:11:16.461Z
console.log(date_str) //Tue Sep 28 2021 12:11:16 GMT+0900 (Korean Standard Time)
console.log(typeof date_now) //object
console.log(typeof date_str) //string
let date_ms_1 = new Date(0)
console.log(date_ms_1) //1970-01-01T00:00:00.000Z
date_ms_1 = new Date(1000 * 3600 * 24)
console.log(date_ms_1) //1970-01-02T00:00:00.000Z 하루 지난 값
let date_string = new Date("2021-09-28")
console.log(date_string) //2021-09-28T00:00:00.000Z
// month 는 0~11월
let date_param_1 = new Date(2021, 0, 1)
console.log(date_param_1) //2020-12-31T15:00:00.000Z
// 끝이 Z는 UTC 기준이다. 우리나라는 -9hour 해야한다.
let date_param_2 = new Date(Date.UTC(2021, 0, 1)) // UTC 고정하는 법
console.log(date_param_2) //2021-01-01T00:00:00.000Z
new Date()
,new Date(miniseconds)
,new Date(datestring)
new Date(year, month, date, hours, minutes, seconds, ms)
날짜 정보 얻기
// 🤔
let date = new Date()
console.log(date) //2021-09-28T03:17:56.836Z
console.log(date.getFullYear()) //2021
console.log(date.getMonth()) //8 > 9월
// 일요일이 0 ~ 토요일이 6
console.log(date.getDay()) //2 > 화요일
console.log(date.getHours()) //12
// UTC 고정된 값 (우리나라로부터 - 15)
console.log(date.getUTCHours()) //9
// ms 단위
console.log(date.getTime()) //1632799299226
console.log(new Date(date.getTime())) //2021-09-28T03:21:39.226Z
//UTC 로부터 얼마나 차이나는지 분 기준으로
console.log(date.getTimezoneOffset()) // -540 => -9시간
- 날짜 정보 얻기 (년/월/일) :
Date.getFullYear()
,Date.getMonth()
,Date.getDate()
- 날짜 정보 얻기 (시/분/초/ms) :
Date.getHours()
,Date.getMinutes()
,Date.getSeconds()
- 주어진 일시 - 1970/1/1 차분(ms) :
Date.getTime()
, 현지시간-표준 시간 차분(min) :Date.getTimezoneOffset()
날짜 정보 설정
let date = new Date()
console.log(date) //2021-09-28T03:17:56.836Z
let ms_year = date.setFullYear(2020, 3, 15)
console.log(date) //2020-04-15T03:25:32.281Z
console.log(ms_year) //1586921132281 > ms
console.log(new Date(ms_year)) //2020-04-15T03:26:13.683Z > date 와 같은 값
date.setDate(1)
console.log(date) //2020-04-01T03:26:55.477Z
// 0으로 지정하면 이전달
date.setDate(0)
console.log(date) //2020-03-31T03:27:18.635Z
date.setHours(date.getHours() + 2) // 현재 시간에서 2시간 더하기
console.log(date) //2020-03-31T05:27:54.202Z
- 날짜 정보 설정 (년/월/일) :
Date.setFullYear()
,Date.setMonth()
,Date.setDate()
- 날짜 정보 설정 (시/분/초/ms) :
Date.setHours()
,Date.setMinutes()
,Date.setSeconds()
parse
let ms_parse = Date.parse("2020-03-31T00:00:00.000") // 로컬기준
console.log(ms_parse) //1585580400000
console.log(new Date(ms_parse)) //2020-03-30T15:00:00.000Z > (UTC0는 +9시간 해야 된다.)
// 애초에 UTC0 로 설정하려면?
ms_parse = Date.parse("2020-03-31T00:00:00.000Z")
console.log(ms_parse) //1585612800000
console.log(new Date(ms_parse)) //2020-03-31T00:00:00.000Z
parse
는 ms 반환- 날짜 정보 설정
- 문자열 기반 날짜 정보 설정 :
Date.parse(YYYY-MM-DDTHH:mm:ss.sssZ)
- YYYY-MM-DD : 날짜 (연-월-일)
- T : 구분 기호
- HH:mm:ss.sss : 시, 분, 초, 밀리초
- Z (option) : 미 설정할 경우 현재 로컬 기준 UTC로, 설정할 경우 UTC+0 기준으로 시간 설정
benchmark
function dateSub(old_date, new_date) {
return new_date - old_date;
}
function getTimeSub(old_date, new_date) {
return new_date.getTime() - old_date.getTime();
}
function benchmark(cb) {
let date1 = new Date("2020-01-01");
let date2 = new Date();
let start = Date.now();
for (let i = 0; i < 100000; i++) {
cb(date1, date2);
}
return Date.now() - start;
}
console.log("dateSub: " + benchmark(dateSub) + "ms") //dateSub: 16ms
console.log("getTimeSub: " + benchmark(getTimeSub) + "ms") //getTimeSub: 5ms
- 성능 측정
- 벤치마크 측정 대상 함수 전호루 시간을 비교하여 알고리즘 성능 측정
- 알고리즘 성능 평가 시 사용
7. N차원 Array
- 배열(Array) 안에 N개 만큼의 배열이 존재하는 객체
- 2,3차원 지도 정보, RGB를 저장하는 2차원 사진 파일 등을 표현할 때 활용 가능
Array[N][M]
2차원 배열
let arr = [
[1,2,3],
[4,5,6],
[7,8,9]
]
console.log(arr) //[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
console.log(arr[0]) //[ 1, 2, 3 ]
console.log(arr[1][0]) //4
console.log(arr.length) // 3
let arr2 = arr.pop()
console.log(arr.length) //2
console.log(arr) //[ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
console.log(arr2) //[ 7, 8, 9 ]
let arr3 = arr.push([10, 11, 12])
console.log(arr.length) //3
console.log(arr) //[ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 10, 11, 12 ] ]
console.log(arr3) // push 된 배열의 최종 길이
let arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
console.log(arr[i][j]);
// 1 2 3 4 5 6 7 8 9
}
}
// 이런식으로 data 저장하는 방법 잘 안 쓰인다.
let fruits = [
["apple", 50],
["banana", 100],
["melon", 3],
];
for (i = 0; i < fruits.length; i++) {
console.log("name : " + fruits[i][0] + " amount : " + fruits[i][1]);
// name : apple amount : 50
// name : banana amount : 100
// name : melon amount : 3
}
array[N][M]
으로 접근하며, 배열(Array) 전체를 push(), pop() 가능- 이중 for loop 를 사용한 2차원 배열 접근
나의 회고 🤫
우와 드디어 Js 대장정 종료다..!
어떤 언어든 가장 그 언어의 자료구조를 활용할 수 있는 컬렉션…너무 어렵다…ㅠㅠ
정말 7,8,9 페이지는 틈날때마다 들려서 살펴봐야겠다.
전체적인 js 문법을 돌아볼수 있었지만 spread 연산자와 함수 중 원시 함수의 불변성을 보장하는 함수를 따로 정리해서 공부해두면 좋을 것 같다.