자바스크립트에서는 원시값(문자열, 숫자 등)을 객체처럼 다룰 수 있다.
원시형의 종류: 문자(string), 숫자(number), bigint, 불린(boolean), 심볼(symbol), null, undefined
객체 : 프로퍼티에 다양한 종류의 값 저장 가능. {} 대괄호를 사용해 만들 수 있음. 함수도 객체의 일종.
원시값을 객체처럼 사용하기.
Object Wrapper : String, Number, Boolean, Symbol, etc.ex) str.toUpperCase()new 를 붙여서 생성자처럼 사용하지 않길 추천. 형변환을 위해 다음과 같이 사용하는 것 추천.
let num = Number("123"); // 문자열을 숫자로 바꿔줌
Null, undefined에 대해서는 메서드 없음.
0이 많이 붙은 큰 숫자 0개의 개수를 'e'뒤에 추가해 표현.
진법
16진수 접두사 : 0x..
8진수 접두사 : 0o...
2진수 접두사 : 0b...
toString(base)
: num.toString(base) 메서드는 base진법으로 num을 표현 후, 문자형으로 변환해 반환
base는 2~36의 값. 몇 진수를 사용할지 정하는 부분.
숫자를 대상으로 메서드 toString 직접 호출 시 점 두 개 사용.
123456..toString(36)
또는 괄호 사용.
(123456).toString(36)
어림수 구하기(rounding)
- Math.floor : 버림(소수점 첫째 자리 기준)
- Math.ceil : 올림
- Math.round : 반올림
- Math.trunc : 소수부 무시.
부정확한 계산.
: 숫자가 이진수로 변환되어 메모리에 저장되면서 정밀도 손실이 발생.
toFixed(n) 메서드를 사용해 어림수를 만드는 것이 가장 신뢰할만한 해결책. (단, 이경우 문자열이 반환됨)
isNaN과 isFinite
isNaN(value) : 인수를 숫자로 변환 후 NaN인지 테스트
isFinite(value) : 인수를 숫자로 변환하고 변환한 숫자가 NaN/Infinity/-Infinity가 아닌 일반 숫자인 경우 true를 반환
빈 문자열이나 공백 문자열은 숫자 관련 함수에서 0으로 취급.
Object.is
'==='처럼 값 비교 시 사용되는 내장 메서드.
NaN끼리 비교 또는 0, -0 비교시 더 나은 결과. 이외에는 동일.
parseInt와 parseFloat
문자열에서 숫자 부분만 추출. (불가능한 지점까지 읽은 숫자를 반환)
parseInt : 정수, parseFloat : 부동 소수점 숫자 반환
기타 수학 함수
- Math.random()
- Math.max(a, b, c,...)/Math.min(a, b, c,..)
- Math.pow(n, power) : n을 power번 거듭제곱한 값을 반환.
자바스크립트에서 문자열은 페이지 인코딩 방식과 상관없이 항상 UTF-16 형식을 따른다.
- 작은따옴표 : ''
- 큰 따옴표 : ""
- 백틱 : ``
백틱은 ${}를 사용해 표현식을 문자열 중간에 삽입 가능.
백틱을 사용해 문자열 여러 줄에 걸쳐 작성 가능.
str.length : 문자열의 길이가 저장되는 프로퍼티 (괄호 미포함)
특정 글자에 접근하기 : str[pos] 또는, str.charAt(pos)를 사용해 해당 position에 있는 글자 접근 가능. (str 은 문자열 변수)
-> 해당 위치에 글자 없으면 []는 undefined, charAT은 빈 문자열 반환
-> for..of 를 사용해 문자열 구성 글자를 대상으로 반복 작업 가능.
문자열 불변성
문자열은 수정 불가 -> 새로운 문자열을 만들어 할당은 가능.
str.indexOf
: str.indexOf(substr, pos) 메서드. 부분 문자열 substr이 문자열 어디에 있는지 위치반환, 없으면 -1 반환.
대소문자 따짐.
includes, startsWith, endsWith
alert( "Widget with id".includes("Widget") ); // true
alert( "Hello".includes("Bye") ); // false
alert( "Widget".startsWith("Wid") ); // true, "Widget"은 "Wid"로 시작합니다.
alert( "Widget".endsWith("get") ); // true, "Widget"은 "get"으로 끝납니다.
substring, substr, slice
str.slice(start [, end]) : 문자열의 start부터 end까지(end는 미포함)를 반환
str.substring(start [, end]) : start와 end 사이에 있는 문자열을 반환합니다. start가 end보다 커도 괜찮음. 동일 결과.
str.substr(start [, length]) : start에서부터 시작해 length 개의 글자를 반환합니다. 길이 기준. 첫째 인수가 음수면 뒤에서부터 개수를 센다.
문자열에 쓸 수 있는 다른 메서드.
- str.trim() : 문자열 앞, 끝 공백문자 제거.
- str.repeat(n) : 문자열 n번 반복
빈 배열 만드는 방법
let arr = new Array();
let arr = []; //주로 사용되는 방법
사용 예)
let fruits = ["사과", "오렌지", "자두"];
alert( fruits[0] ); // 사과
//요소 수정
fruits[2] = '배'; // 배열이 ["사과", "오렌지", "배"]로 바뀜
//요소 개수 확인 .length 메서드 사용
alert( fruits.length ); // 3
//요소 전체 출력
alert( fruits ); // 사과,오렌지,배
trailing 쉼표
: 배열의 마지막 요소 뒤에 쉼표 사용 가능
pop·push와 shift·unshift
큐(Queue) First-in-First-Out 선입 선출
- push : 맨 끝에 요소 추가
- shift : 제일 앞 요소를 꺼내고, 남아있는 요소를 앞으로 밀어줌.
스택(Stack) Last-in--First-Out 후입선출
- push : 요소를 스택 끝에 추가
- pop : 스택 끝 요소 추출
배열 끝 pop, push
//pop
let fruits = ["사과", "오렌지", "배"];
alert( fruits.pop() ); // 배열에서 "배"를 제거하고 제거된 요소를 얼럿창에 띄웁니다.
alert( fruits ); // 사과,오렌지
//push
let fruits = ["사과", "오렌지"];
fruits.push("배");
alert( fruits ); // 사과,오렌지,배
배열 앞 shift, unshift.
//shift : 배열 앞 요소 제거, 제거한 요소 반환
let fruits = ["사과", "오렌지", "배"];
alert( fruits.shift() ); // 배열에서 "사과"를 제거하고 제거된 요소를 얼럿창에 띄웁니다.
alert( fruits ); // 오렌지,배
//unshift : 배열 앞에 요소 추가
let fruits = ["오렌지", "배"];
fruits.unshift('사과');
alert( fruits ); // 사과,오렌지,배
사용 예)
let fruits = ["사과"];
fruits.push("오렌지", "배");
fruits.unshift("파인애플", "레몬");
// ["파인애플", "레몬", "사과", "오렌지", "배"]
alert( fruits );
push와 pop은 빠르지만 shift와 unshift는 느리다
length 메소드를 사용해 배열 길이 수정
let arr = [1, 2, 3, 4, 5];
arr.length = 2; // 요소 2개만 남기고 잘라봅시다.
alert( arr ); // [1, 2]
arr.length = 5; // 본래 길이로 되돌려 봅시다.
alert( arr[3] ); // undefined: 삭제된 기존 요소들이 복구되지 않습니다.
new Array()
: 잘 사용되지 않음. 새로 선언 시 배열의 모든 요소가 undefined이기 때문.
배열을 다차원으로 사용가능.
toString
배열에 toString메서드가 구현되어 있음.
let arr = [1, 2, 3];
alert( arr ); // 1,2,3
alert( String(arr) === '1,2,3' ); // true
아래 방법을 사용하면 모든 요소를 대상으로 반복 작업을 할 수 있습니다.
Splice : splice(pos, deleteCount, ...items) – pos부터 deleteCount개의 요소를 지우고, items 추가하기
Slice : slice(start, end) – start부터 end 바로 앞까지의 요소를 복사해 새로운 배열을 만듦
Concat : concat(...items) – 배열의 모든 요소를 복사하고 items를 추가해 새로운 배열을 만든 후 이를 반환함. items가 배열이면 이 배열의 인수를 기존 배열에 더해줌
** concat : 배열의 요소를 복사해 활용, 객체가 인자로 넘어올 때 Symbol.isConcatSpreadable이 있으면 concat은 이 객체를 배열처럼 취급.
ex)
let arr = [1, 2];
let arrayLike = {
0: "something",
1: "else",
[Symbol.isConcatSpreadable]: true,
length: 2
};
alert( arr.concat(arrayLike) ); // 1,2,something,else
원하는 요소 찾기
indexOf/lastIndexOf(item, pos) : indexOf/lastIndexOf(item, pos) – pos부터 원하는 item을 찾음. 찾게 되면 해당 요소의 인덱스를, 아니면 -1을 반환함
include(value) : includes(value) – 배열에 value가 있으면 true를, 그렇지 않으면 false를 반환함
find/filter(func) : func의 반환 값을 true로 만드는 첫 번째/전체 요소를 반환함
배열 전체 순회하기
forEach(func) : 모든 요소에 func호출. 결과 반환되지 않음
ex)
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
alert(`${item} is at index ${index} in ${array}`);
});
배열 변형하기
map : 배열 요소 전체를 대상으로 함수를 호출하고, 함수 호출 결과를 배열로 반환한다.
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
alert(lengths); // 5,7,6
sort : 배열 정렬하고 정렬된 배열 반환
=> 요소가 문자열로 취급되어 재 정렬 되므로, 숫자 크기로 정렬시키려면 arr.sort()에 값 두 개를 비교해 반환하는 함수를 넘겨줘야 한다.
reverse() : 배열을 뒤집어 반환
split/join : 문자열을 배열로, 배열을 분자열로 변환
let arr = ['Bilbo', 'Gandalf', 'Nazgul'];
let str = arr.join(';'); // 배열 요소 모두를 ;를 사용해 하나의 문자열로 합칩니다.
alert( str ); // Bilbo;Gandalf;Nazgul
reduce(func, initial) : 요소를 차례로 돌면서 func 호출. 반환값은 다음 함수 호출에 전달함. 최종적으로 하나의 값이 도출됨
let value = arr.reduce(function(accumulator, item, index, array) {
// ...
}, [initial]);
//-- example --
let arr = [1, 2, 3, 4, 5];
let result = arr.reduce((sum, current) => sum + current, 0);
alert(result); // 15
- accumulator : 이전 함수 호출의 결과. initial은 함수 최초 호출 시 사용되는 초깃값
- item : 현재 배열 요소
- index : 요소의 위치
- array : 배열
=> arr.reduceRight도 reduce와 동일한 기능을 하지만 배열의 오른쪽부터 연산 수행.
Array.isArray(arr) – arr이 배열인지 여부를 판단함
- typeof로 배열을 확인할 경우 객체로 반환됨.
Array.isArray(value)를 통해 배열이라면 true 반환받을 수 있음.
배열 메서드와 'thisArg'
: callback 실행 시 this로 사용하는 값. 함수를 호출할 수 있는 대부분의 배열 메서드는 thisArg라는 인자를 옵셔널 한 인자로 (맨 마지막인자로) 받을 수 있다.
자주 사용 되지는 않음.
filter : 충족할 조건이 여러 개면 arr.filter(fn) 사용
let results = arr.filter(function(item, index, array) {
// 조건을 충족하는 요소는 results에 순차적으로 더해집니다.
// 조건을 충족하는 요소가 하나도 없으면 빈 배열이 반환됩니다.
});
조건에 맞는 요소 전체를 담은 배열을 반환함
map : 배열 요소 전체를 대상으로 함수 호출, 결과를 배열로 반환.
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
alert(lengths); // 5,7,6
iterable 객체
for..of 를 사용할 수 있는 객체를 iterable이라고 부른다.
문자열과 같은 내장 이터러블에 Symbol.iterator를 사용해 배열에 반복문을 사용하듯 사용할 수 있다.
obj[Symbol.iterator]
Array.from(obj[, mapFn, thisArg])를 사용하면 유사 배열인 obj를 Array로 만들 수 있다.
Map : 키(key)가 있는 데이터를 저장.
Set : 중복을 허용하지 않는 값을 모아놓은 컬렉션. 키 없는 값이 저장됨.
Object.entries(obj) : 객체를 맵으로 바꾸는 방법. [키, 값] 요소로 가지는 이터러블을 반환.
Object.fromEntries : 맵을 객체로 바꾸는 방법. (각 요소가 [키, 값] 쌍인 배열을 객체로 바꿔준다.)
WeakMap and WeakSet
배열의 요소는 배열이 메모리에 남아있는 한, Garbage Collector에 의해 메모리에서 삭제되지 않는다.
let john = { name: "John" };
let array = [ john ];
john = null; // 참조를 null로 덮어씀
// john을 나타내는 객체는 배열의 요소이기 때문에 가비지 컬렉터의 대상이 되지 않습니다.
// array[0]을 이용하면 해당 객체를 얻는 것도 가능합니다.
alert(JSON.stringify(array[0]));
WeakMap
: 키 값으로 객체를 사용한다. 이 경우 반복 작업과, key(), values(), entries() 메서드 지원하지 않음.
let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // 참조를 덮어씀
// john을 나타내는 객체는 이제 메모리에서 지워집니다!
데이터가 특정 시간 동안에만 유효하면 되는 경우 사용. ex) cache data.
WeakSet
: 객체만 저장할 수 있다. 저장된 객체가 도달 불가능한 상태가 되면 해당 객체는 메모리에서 삭제됨.
객체엔 주요 자료, WeakMap, WeakSet에는 부수적인 자료를 저장.
객체에 사용가능한 메서드
- Object.keys(obj), Object.values(obj), Object.entries(obj)
심볼형 프로퍼티 무시.
객체 변환하기
- Object.entries, Object.fromEntries를 순차적으로 적용해 배열 전용 메서드 사용 가능.
let prices = {
banana: 1,
orange: 2,
meat: 4,
};
let doublePrices = Object.fromEntries(
// 객체를 배열로 변환해서 배열 전용 메서드인 map을 적용하고 fromEntries를 사용해 배열을 다시 객체로 되돌립니다.
Object.entries(prices).map(([key, value]) => [key, value * 2])
);
alert(doublePrices.meat); // 8
받은 값을 복사해 변수로 분해해 줌. 배열의 요소를 직접 변수에 할당하는 것보다 코드 양이 줄어든다.
배열뿐만 아니라 이터러블을 사용해 구조 분해 할당을 사용할 수도 있다.
let [a, b, c] = "abc"; // ["a", "b", "c"]
let [one, two, three] = new Set([1, 2, 3]);
Object.entries()로 반복하기
-> Object.entries와 destructuring assignment를 함께 사용.
let user = {
name: "John",
age: 30
};
// 객체의 키와 값 순회하기
for (let [key, value] of Object.entries(user)) {
alert(`${key}:${value}`); // name:John, age:30이 차례대로 출력
}
변수 교환 트릭
let guest = "Jane";
let admin = "Pete";
// 변수 guest엔 Pete, 변수 admin엔 Jane이 저장되도록 값을 교환함
[guest, admin] = [admin, guest];
alert(`${guest} ${admin}`); // Pete Jane(값 교환이 성공적으로 이뤄졌습니다!)
'…'로 나머지 요소 가져오기
나머지 값들을 한데 모아서 저장하고 싶을 때 사용.
let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert(name1); // Julius
alert(name2); // Caesar
// `rest`는 배열입니다.
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2
요약
객체 분해하기 :
let {prop : varName = default, ...rest} = object
배열 분해하기 :
let [item1 = default, item2, ...rest] = array
자바스크립트에서는 Date객체를 사용해 날짜와 시간을 나타내고, 날짜와 시간이 늘 함께 저장된다.
월은 0-11, 요일(getDay()로 얻을 수 있음)도 0(일요일)-6(토요일)
Date 객체엔 autocorrection 기능이 있어 범위에 벗어난 값을 설정하려고 하면 자동으로 값이 수정된다.
일정 시간 이후의 날짜나 시간을 구할 때 사용할 수 있음.
Date 객체를 숫자로 변경해 시간차 측정하기.
let date = new Date();
alert(+date); // 타임스탬프(date.getTime()를 호출한 것과 동일함)
Date.now()
=> 타임스탬프(2017년 1월 1일 0시부터 현재 몇 밀리초가 지났는지 보여줌)를 반환하는 메서드. Date 객체를 따로 만들어 작업하지 않으므로 좀 더 빠르게 사용가능.
* Date객체 생성 시
let start = new Date(); // 측정 시작
// 원하는 작업을 수행
for (let i = 0; i < 100000; i++) {
let doSomething = i * i * i;
}
let end = new Date(); // 측정 종료
alert( `반복문을 모두 도는데 ${end - start} 밀리초가 걸렸습니다.` );
* Date.now() 사용 시
let start = Date.now(); // 1970년 1월 1일부터 현재까지의 밀리초
// 원하는 작업을 수행
for (let i = 0; i < 100000; i++) {
let doSomething = i * i * i;
}
let end = Date.now(); // done
alert( `반복문을 모두 도는데 ${end - start} 밀리초가 걸렸습니다.` ); // Date 객체가 아닌 숫자끼리 차감함
Date.parse와 문자열
Date.parse 메서드를 사용하면 'YYYY-MM-DDTHH:mm:ss.sssZ' 형식으로 쓰인 문자열을 날짜로 읽어올 수 있다.
네트워크를 통해 객체를 어딘가로 보내거나, 로깅 목적으로 객체를 출력해야 할 경우 객체를 문자열로 전환해야한다.
JSON.stringify : 객체를 JSON으로 바꿔주는 메서드
let student = {
name: 'John',
age: 30,
isAdmin: false,
courses: ['html', 'css', 'js'],
wife: null
};
let json = JSON.stringify(student);
alert(typeof json); // 문자열이네요!
alert(json);
/* JSON으로 인코딩된 객체:
{
"name": "John",
"age": 30,
"isAdmin": false,
"courses": ["html", "css", "js"],
"wife": null
}
*/
중첩 객체도 알아서 문자열로 바꿔주지만, 순환참조 (서로를 참조하는 경우)가 있으면 원하는 대로 객체를 문자열로 바꾸는게 불간으.
JSON.stringify의 전체 문법
let json = JSON.stringify(value, [replacer, space])
* space는 가독성을 높이기 위해 사용.
커스텀 "toJSON"
let room = {
number: 23,
toJSON() {
return this.number;
}
};
let meetup = {
title: "Conference",
room
};
alert( JSON.stringify(room) ); // 23
alert( JSON.stringify(meetup) );
/*
{
"title":"Conference",
"room": 23
}
*/
커스텀 메서드 toJSON을 추가하면 JSON.stringify가 이를 감지하여 JSON으로 형변환해줌.
JSON.parse : JSON을 객체로 바꿔주는 메서드
let value = JSON.parse(str, [reviver]);
- str : JSON 형식의 문자열
- reviver : (key, value)쌍을 대상으로 호출되는 function(key, value) 형태의 함수로 값을 변경시킬 수 있다.
*** JSON은 주석을 지원하지 않음. 주석 추가할 경우 유효하지 않은 형식이 된다.
reviver 사용하기
- JSON을 객체로 변환할때, Date와 같은 다른 유형으로 변경하기 위해서는 JSON.parse의 두 번째 인수 reviver사용
let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';
let meetup = JSON.parse(str, function(key, value) {
if (key == 'date') return new Date(value);
return value;
});
alert( meetup.date.getDate() ); // 이제 제대로 동작하네요!
javascript.info - 함수 심화학습(2) (0) | 2022.12.29 |
---|---|
javascript.info - 함수 심화학습 (0) | 2022.12.29 |
javascript.info - 객체 기본(2) (0) | 2022.12.27 |
javascript.info - 객체 기본(1) (0) | 2022.12.27 |
javascript.info - 코드 품질(2) (0) | 2022.12.27 |