상세 컨텐츠

본문 제목

javascript.info - 자료구조와 자료형

개발공부/개발공부

by Dal_pang 2022. 12. 28. 17:52

본문

원시값의 메서드

자바스크립트에서는 원시값(문자열, 숫자 등)을 객체처럼 다룰 수 있다.

원시형의 종류:  문자(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

  • Infinity와 -Infinity – 그 어떤 숫자보다 큰 혹은 작은 특수 숫자 값
  • NaN – 에러를 나타내는 값

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

아래 방법을 사용하면 모든 요소를 대상으로 반복 작업을 할 수 있습니다.

  • for (let i=0; i<arr.length; i++) – 가장 빠른 방법이고 오래된 브라우저와도 호환됩니다.
  • for (let item of arr) – 배열 요소에만 사용되는 모던한 문법입니다.
  • for (let i in arr) – 배열엔 절대 사용하지 마세요.

배열과 메서드

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, values, entries

 객체에 사용가능한 메서드

- 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

구조 분해 할당 (Destructuring assignment)

받은 값을 복사해 변수로 분해해 줌. 배열의 요소를 직접 변수에 할당하는 것보다 코드 양이 줄어든다.

배열뿐만 아니라 이터러블을 사용해 구조 분해 할당을 사용할 수도 있다.

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 객체와 날짜 

자바스크립트에서는 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과 메서드

네트워크를 통해 객체를 어딘가로 보내거나, 로깅 목적으로 객체를 출력해야 할 경우 객체를 문자열로 전환해야한다.

 

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() ); // 이제 제대로 동작하네요!
728x90

관련글 더보기