원시값의 메서드
원시값
- 원시형의 종류는 문자(string), 숫자(number), bigint, boolean, symbol, null, undefined 총 7가지
객체
- 프로퍼티에 다양한 종류의 값을 저장할 수 있습니다.
- {name: 'kim', age:1} 대괄호 {}를 사용해 만들 수 있음. 함수도 객체의 일종.
원시값을 객체처럼 사용하기
- 문자열이나 숫자와 같은 원시값을 다루어야 하는 작업이 많은데, 메서드를 사용하면 작업을 수월하게 할 수 있을 것 같다는 생각이 들었음.
- 그런데 원시값은 가능한 한 빠르고 가벼워야 함.
해결책
- 원시값은 원시값 그대로 남겨둬 단일 값 형태를 유지합니다.
- 문자열, 숫자, 불린, 심볼의 메서드와 프로퍼티에 접근할 수 있도록 언어 차원에서 허용합니다.
- 이를 가능하게 하기 위해, 원시값이 메서드나 프로퍼티에 접근하려 하면 추가 기능을 제공해주는 특수한 객체, "원시 래퍼 객체(object wrapper)" 를 만들어줍니다. 이 객체는 곧 삭제됩니다.
let str = "hello";
alert(str.toUpperCase());
- 문자열 str은 원시값이므로 원시값의 프로퍼티(toUpperCase)에 접근하는 순간 특별한 객체가 만들어집니다. 이 객체는 문자열의 값을 알고 있고, toUpperCase() 와 같은 유용한 메서드를 가지고 있습니다.
- 메서드가 실행되고, 새로운 문자열이 반환됩니다.
- 특별한 객체는 파괴되고, 원시값 str만 남습니다.
let str = "hello";
str.test = 5; //(*)
alert(str.test);
// 결과
- undefined(비 엄격 모드)
- an error(엄격 모드)
// (*) 로 표시한 줄에서 무슨 일이 일어났는지
- str의 프로퍼티에 접근하려 하면 "래퍼 객체"가 만들어집니다.
- 엄격 모드에선 래퍼 객체를 수정하려 할 때 에러가 발생합니다.
- 비 엄격 모드에선 에러가 발생하지 않습니다. 래퍼 객체에 프로퍼티 test가 추가되죠. 그런데 래퍼 객체는 바로 삭제되기 때문에 마지막 줄이 실행될 땐 프로퍼티 test를 찾을 수 없습니다.
숫자형
모던 자바스크립트는 숫자를 나타내는 두 가지 자료형을 지원
- 일반적인 숫자는 '배정밀도 부동소수점 숫자(double precision floating point number)' 로 알려진 64비트 형식의 IEEE-754에 저장.
- 임의의 길이를 가진 정수는 BigInt 숫자로 표현.
숫자를 입력하는 방법
let billion = 1000000000;
let billion1 = 1e9; // 1000000000
let ms = 0.000001;
let ms1 = 1e-6; // 0.000001
let a = 0xff; // 255 16진수
let b = 0xFF; // 255 16진수
let c = 0b11111111; // 255 2진수
let d = 0o377; // 255 8진수
num.toString(base) : base진법으로 num을 표현한 후, 이를 문자형으로 반환
let num = 255;
alert(num.toString(16)); // ff
alert(num.toString(2)); // 1111111
어림수 구하기
Math.floor : 소수점 첫째자리에서 내림(버림)
Math.ceil : 소수점 첫째자리에서 올림
Math.round : 소수점 첫째 자리에서 반올림
toFixed(n) : n번째 수까지 어림수를 구한 후 이를 문자형으로 반환해주는 메서드
let a = Math.floor(3.111);
let b = Math.ceil(3.111);
let c = Math.round(3.111);
let d = 3.111;
console.log(a); // 3
console.log(b); // 4
console.log(c); // 3
console.log(d.toFixed(1)); // 3.1
부정확한 계산
console.log(0.1 + 0.2); // 0.30000000000000004
숫자는 0과 1로 이루어진 이진수로 변환되어 연속된 메모리 공간에 저장.
10진법을 사용하면 쉽게 표현할 수 있는 0.1, 0.2같은 분수는 이진법으로 표현하면 무한소수가 됨.
isNaN, isFinite
Infinity, -Infinity : 그 어떤 숫자보다 큰 혹은 작은 특수 숫자값
NaN : 에러값을 나타내는 값
isNaN(value) : 인수를 숫자로 변환한 다음 NaN 테스트 함
isFinite(value) : 인수를 숫자로 변환하고 변환한 숫자가 NaN/Infinity/-Infinity가 아닌 일반 숫자인 경우 true 반환.
-> 문자열이 일반 숫자인지 검증하는데 사용.
console.log(isNaN(NaN)); // true
console.log(isNaN("str")); // true
console.log(NaN === NaN); // false, 자기 자신을 포함하여 그 어떤 값과도 같지 않다는 점.
console.log(isFinite("15")); // true
console.log(isFinite("str")); // false, NaN 이기 때문
console.log(isFinite(Infinity)); // false, Infinity 이기 때문
let num = +prompt("숫자를 입력하세요", '');
alert(isFinite(num));
Object.is
Object.is는 === 값을 비교할 때 사용되는 특별한 내장 메서드인데, 아래와 같은 두 가지 케이스에선 신뢰할 수 있는 결과를 보여줌.
Object.is(NaN, NaN); // true
Object.is(0, -0); // false
문자열
작은 따옴표와 큰 따옴표는 기능상 차이가 없습니다.
템플릿 리터럴(template literal)
- 백틱엔 특별한 기능이 있습니다.
- 표현식을 ${...}로 감싸고 이를 백틱으로 감싼 문자열 중간에 넣어주면 해당 표현식을 문자열 중간에 쉽게 삽입할 수 있음.
문자열.length : 함수가 아니고, 숫자가 저장되는 프로퍼티, 문자열의 길이 저장.
특정 글자에 접근하기
let str = 'hello';
console.log(str[0]);
console.log(str.charAt(0));
console.log(str[1000]); // undefined
console.log(str.charAt(1000)); // '' (빈 문자열)
let str = "hello";
str.toUpperCase();
str.toLowerCase();
str.indexOf('e');
"hello".includes("lo");
"hello".startsWith("he");
"hello".endsWith("lo");
str.slice(0, 2);
배열
- Push : item를 배열 끝에 더해줍니다.
- pop : 배열 끝 요소를 제거하고, 제거한 요소를 반환합니다.
- Shift : 배열 처음 요소를 제거하고, 제거한 요소를 반환합니다.
- Unshift : items를 배열 처음에 더해줍니다.
반복문 // 배열에서만 사용가능.
let fruits = ['사과', '오렌지', '자두'];
for(let fruit of fruits) {
alert(fruit);
}
'length 프로퍼티'
length 프로퍼티는 배열 내 요소의 개수가 아니라 가장 큰 인덱스에 1을 더한 값.
let arr = [];
arr[111] = 22;
alert(arr.length); // 112
배열과 메서드
splice
arr.splice(index[, deleteCount, elem1, ..., eleN])
slice
arr.slice([start], [end])
concat
arr.concat(arg1, arg2)
forEach
arr.forEach(function(item, index, array) {
// 요소에 무언가를 할 수 있음.
});
indexOf(item, from) / lastIndexOf(item, from) / includes(item, from)
find
let result = arr.find(function(item, index, array) {
// true가 반환되면 반복이 멈추고 해당 요소를 반환합니다.
// 조건에 해당하는 요소가 없으면 undefined를 반환합니다.
});
filter
let results = arr.filter(function(item, index, array) {
// 조건을 충족하는 요소는 results에 순차적으로 더해집니다.
// 조건을 충족하는 요소가 하나도 없으면 빈 배열이 반환됩니다.
});
map
let result = arr.map(function(item, index, array) {
// 요소 대신 새로운 값을 반환합니다.
});
sort(), reverse(), split(), join()
Array.isArray
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(Array.isArray({}); // false
console.log(Array.isArray([]); // true
iterable 객체
반복 가능한 (iterable) 객체는 배열을 일반화한 객체입니다.
for.. of 를 사용할 수 있는 객체를 이터러블이라고 부름.
- iterable에는 메서드 Symbol.iterator 가 반드시 구현되어 있어야 함.
- Obj[Symbol.iterator]의 결과는 이터레이터, 이터레이터는 이어지는 반복 과정을 처리.
- 이터레이터엔 객체{done: Boolean, value:any}을 반환하는 메서드 next()가 반드시 구현되어 있어야 함. 여기서 done: true는 반복이 끝남을 의미. 그렇지 않은 경우엔 value가 다음 값이 된다.
맵과 셋
맵 map
- new Map() : 맵을 만든다.
- Map.set(key, value) : key를 이용해 value를 저장.
- Map.get(key) : key에 해당하는 값을 반환, key가 존재하지 않으면 undefined를 반환.
- Map.has(key) : key가 존재하면 true, 존재하지 않으면 false를 반환.
- map.delete(key) : key에 해당하는 값을 삭제.
- Map.clear() : 맵 안에 모든 요소를 제거.
- map.size - 요소의 개수를 반환.
맵은 키로 객체를 허용합니다.
맵은 삽입된 순서를 기억합니다.
맵의 요소에 반복 작업하기
- Map.keys() : 각 요소의 키를 모은 반복 가능한(iterable) 객체 반환.
- Map.values() : 각 요소의 값을 모든 이터러블 객체를 반환.
- Map.entries() : 요소의 [키, 값] 한 쌍으로 하는 이터러블 객체를 반환.
Object.entries : 객체를 맵으로 바꾸기
Object.fromEntries : 맵을 객체로 바꾸기
셋 set
중복을 허용하지 않은 값을 모아놓은 특별한 컬렉션, 셋에 키가 없는 값이 저장.
- new Set(iterable) : 셋을 만듭니다. 이터러블 객체를 전달 받으면 그 안의 값을 본사해 셋에 넣어줌.
- set.add(value) : 값을 추가하고 셋 자신을 반환.
- set.delete(value) : 값을 제거.
- set.has(value) : 셋 내에 값이 존재하면 true, 아니면 false
- Set.clear() : 셋을 비웁니다.
- Set.size : 요소의 갯수 반환.
위크맵과 위크셋
맵에서 객체를 키로 사용한 경우, 맵이 메모리에 있는 한 객체도 메모리에 남음. 가비지 컬렉터의 대상이 되지 않음.
위크맵(WeakMap) 을 사용하면 키로 쓰인 객체가 가비지 컬렉션의 대상이 됨.
- 위크맵의 키는 반드시 객체여야 함.
let john = { name: "John" };
let map = new Map();
map.set(john, "...");
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // 참조를 null로 덮어씀
// john을 나타내는 객체는 맵 안에 저장되어있습니다.
// map.keys()를 이용하면 해당 객체를 얻는 것도 가능합니다.
for(let obj of map.keys()){
alert(JSON.stringify(obj));
}
alert(map.size); // 1
alert(weakMap.size); // undefined join = null이 된 시점에서 메모리 삭제 대상.
위크맵을 사용하면 수동으로 삭제해줄 필요 없음, 키가 되는 객체가 사라지면, 가비지 컬렉터의 대상이 되므로 .
// 📁 visitsCount.js
let visitsCountMap = new WeakMap(); // 위크맵에 사용자의 방문 횟수를 저장함
// 사용자가 방문하면 방문 횟수를 늘려줍니다.
function countUser(user) {
let count = visitsCountMap.get(user) || 0;
visitsCountMap.set(user, count + 1);
}
위크셋은 셋과 유사한데, 객체만 저장할 수 있다는 점이 다름.원시값은 저장 불가.
Object.keys, values, entries
맵 | 객체 | |
---|---|---|
호출 문법 | map.keys() | Obj.keys()가 아닌 Object.keys(obj); |
반환 값 | iterable 객체 | 진짜 배열 |
let user = {
name : 'kim',
age: 1,
};
console.log(Object.keys(user)); // ["name", "age"]
console.log(Object.values(user)); // ["kim", 1]
console.log(Object.entries(user)); ["name", "kim"],["age", 1]
- Object.entries(obj)를 사용해 객체, 키 쌍을 요소로 갖는 배열을 얻음.
- 1에서 만든 배열에 map등 배열 전용 메서드 적용
- 2에서 반환된 배열에 Object.fromEntries(array)를 적용해 배열을 다시 객체로 되돌림.
let prices = {
banana: 1,
apple: 2,
meat: 4,
};
let doublePrices = Object.fromEntries(
Object.entries(prices)
.map(([key, value]) => [key, value * 2])
);
alert(doublePrices);
구조 분해 할당
배열 분해하기
let arr = ["Bora", "Lee"]
let [firstName, surname] = arr;
alert(firstName);
alert(surname);
객체 분해하기
let options = {
title: "Menu",
width: 100,
height: 200
};
let {title, width, height} = options;
console.log(title);
console.log(width);
console.log(height);
Date 객체와 날짜
let now = new Date();
console.log(now.getFullYear()); // 2020
console.log(now.getMonth()); // 7 (0 ~ 11) // 8월
console.log(now.getDate()); // 23
console.log(now.getDay()); // 0 (0 ~ 6) // 일요일
Date.parse(str)
- YYYY-MM-DD – 날짜(연-월-일)
- "T" – 구분 기호로 쓰임
- HH:mm:ss.sss – 시:분:초.밀리초
JSON과 메서드
JSON.stringify
– 객체를 JSON으로 바꿔줍니다.JSON.parse
– JSON을 객체로 바꿔줍니다.
문자열은 큰따옴표로 감싸야 합니다. JSON에선 작은따옴표나 백틱을 사용할 수 없습니다
객체 프로퍼티 이름은 큰따옴표로 감싸야 합니다
JSON.stringify
호출 시 무시되는 프로퍼티는 아래와 같습니다.
- 함수 프로퍼티 (메서드)
- 심볼형 프로퍼티 (키가 심볼인 프로퍼티)
- 값이
undefined
인 프로퍼티
space로 가독성 높이기
JSON.stringify(value, replacer, space)
의 세 번째 인수 space
는 가독성을 높이기 위해 중간에 삽입해 줄 공백 문자 수를 나타냅니다.
let user = {
name: "John",
age: 25,
roles: {
isAdmin: false,
isEditor: true
}
};
alert(JSON.stringify(user, null, 2));
//
/* 공백 문자 두 개를 사용하여 들여쓰기함:
{
"name": "John",
"age": 25,
"roles": {
"isAdmin": false,
"isEditor": true
}
}
*/
'자바스크립트' 카테고리의 다른 글
함수 심화학습, 객체 프로퍼티 설정 (0) | 2020.08.30 |
---|---|
웹 게임을 만들며 배우는 자바스크립트 예제2 (0) | 2020.08.23 |
객체: 기초 (0) | 2020.08.23 |
웹 게임을 만들며 배우는 자바스크립트 (0) | 2020.08.16 |
웹 게임을 만들며 배우는 자바스크립트 예제 (0) | 2020.08.16 |