[모던자바스크립트] 자료구조와 자료형 정리

박재윤·2021년 1월 11일

자바스크립트

목록 보기
4/11

원시값의 메서드

  • 자바스크립트에서 원시값을 객체처럼 다룰 수 있게 한다.

원시값을 객체처럼 사용하는 방법

  1. 원시값을 원시값 그대로 둔다.
  2. 원시값의 메서드와 프로퍼티에 접근할 수 있도록 언어차원에서 허용한다.
  3. 원시값이 메서드나 프로퍼티에 접근하려 하면 추가 기능을 제공해주는 특수한 객체를 만들어 사용하고 이후에 삭제한다.

예를들어,

let str = "Hello";

alert( str.toUpperCase() ); // HELLO

위와 같은 코드가 있을 때 다음과 같은 과정을 거친다.

  1. 문자열 str은 원시값이므로 원시값의 프로퍼티에 접근하는 순간 wrapper 객체가 만들어진다.
  2. 메서드가 실행이 된다.
  3. wrapper 객체가 사라진다.

⚠️String/Number/Boolean를 생성자론 쓰지 맙시다.

alert( typeof 0 ); // "number"

alert( typeof new Number(0) ); // "object"!

아래는 괜찮다.

let num = Number("123"); // 문자열을 숫자로 바꿔줌

원시 객체에 메서드를 추가하려고 하면?

let str = "Hello";

str.test = 5; // (*)

alert(str.test);
  1. 엄격모드일 경우 에러가 발생한다.
  2. 비엄격모드일 경우 에러가 발생하지 않고 test가 추가된다. 하지만 wrapper 객체가 즉시 사라지므로 alert가 되지는 않는다.

숫자형

일반적인 숫자는 IEEE-754의 부동소수점으로 표현이 된다. 이 숫자는 2532^{53}이상이거나 253-2^{53}이하일 수 없기 때문에 BigInt가 만들어졌다.

숫자 표기 방법

let billion = 1000000000;

let billion = 1e9;

let a = 0b11111111; // 255의 2진수
let b = 0o377; // 255의 8진수
let c = 0xff; // 255의 16진수

메서드

toString()

숫자를 원하는 진법으로 바꾼 후 문자로 반환한다.

let num = 255;

alert( num.toString(16) );  // ff
alert( num.toString(2) );   // 11111111

점 두개와 메서드 호출
123456..toString(36)에 있는 점 두 개는 오타가 아닙니다. 위 예시처럼 숫자를 대상으로 메서드 toString을 직접 호출하고 싶다면 숫자 다음에 점 두 개 ..를 붙여야 합니다.

123456.toString(36)처럼 점을 한 개만 사용하면, 첫 번째 점 이후는 소수부로 인식되어 에러가 발생할 수 있습니다. 점을 하나 더 추가하면 자바스크립트는 소수부가 없다고 판단하고 함수를 호출합니다.

(123456).toString(36)도 가능합니다.

floor

버림 -1.32 -1.4

ceil

올림

round

반올림

trunc

소수부 무시 -1.32 -1.3

toFixed

n번째 자리까지 반올림해서 어림수를 구한 후 문자열로 반환한다.

isNaN

인수를 숫자로 변환한 다음 NaN인지 테스트

NaN은 어떠한 값과 일치 연산을 해도 false가 반환되기 때문에 isNaN이 필요하다.

parseInt

Number()와 다른 점은 불가능할 때까지 문자열에서 숫자를 읽고 숫자로 변환한다는 점이다. 두 번째 인수로 진수를 결정해줄 수도 있다.

alert( parseInt('100px') ); // 100
alert( parseFloat('12.5em') ); // 12.5

alert( parseInt('12.3') ); // 12, 정수 부분만 반환됩니다.
alert( parseFloat('12.3.4') ); // 12.3, 두 번째 점에서 숫자 읽기를 멈춥니다.

문자열

메소드

indexOf(subStr, pos)

subStr의 위치를 pos부터 시작해서 찾는다.

let str = 'Widget with id';

alert( str.indexOf('id', 2) ) // 12

includes(substr, pos)

str의 부분 문자열 substr이 있는지를 확인

alert( "Widget".includes("id") ); // true
alert( "Widget".includes("id", 3) ); // false, 세 번째 위치 이후엔 "id"가 없습니다.

str.startsWith, str.endsWith

str이 substr로 시작하는지/끝나는지 확인

str.slice(start [, end])

문자열의 start부터 end까지(end는 미포함)를 반환. 음수를 허용한다.

str.substring(start [, end])

start와 end 사이에 있는 문자열을 반환. substring은 slice와 다르게 start가 end보다 커도 된다. 음수를 허용하지 않는다.

str.substr(start [, length])

start에서부터 시작해 length 개의 글자를 반환. start위치가 음수가 될 수 있다.

배열

  • 배열 선언
let arr = new Array();
let arr = [];
  • 배열의 요소엔 제약이 없다.

배열의 내부 동작 원리

  • 배열의 본질은 객체
  • 키가 숫자라는 점이 다름.
  • 배열은 객체에 속한다.
  • 배열의 요소를 인접한 메모리에 저장

for of vs for in

for of는 현재 요소의 인덱스는 얻을 수 없고 값만 얻을 수 있다. 배열의 요소를 대상으로 반복 작업할 때 사용한다.

for in은 모든 프로퍼티를 대상으로 순회한다. 키가 숫자가 아닌 프로퍼티도 순회대상에 포함된다. 객체와 사용할 때 최적화되어 있어서 더 느리다.

toString

쉼표로 구분한 문자열이 반환된다.

let arr = [1, 2, 3];

alert( arr ); // 1,2,3
alert( String(arr) === '1,2,3' ); // true

reduceRight

reduce와 동일하지만 오른쪽부터 계산

thisArg

thisArg는 함수의 this가 된다.

let army = {
  minAge: 18,
  maxAge: 27,
  canJoin(user) {
    return user.age >= this.minAge && user.age < this.maxAge;
  }
};

let users = [
  {age: 16},
  {age: 20},
  {age: 23},
  {age: 30}
];

// army.canJoin 호출 시 참을 반환해주는 user를 찾음
let soldiers = users.filter(army.canJoin, army);

alert(soldiers.length); // 2
alert(soldiers[0].age); // 20
alert(soldiers[1].age); // 23

Iterable객체

iteratble 객체는 배열을 일반화한 객체

iterable 객체를 만들기 위해서는 Symbol.iterator라는 메소드를 추가해야한다.

Symbol.iterator 진행 과정

  1. for..of가 시작되자마자 for..of는 Symbol.iterator를 호출
  2. 이후 for..of는 반환된 객체(이터레이터)만을 대상으로 동작
  3. for..of에 다음 값이 필요하면, for..of는 이터레이터의 next()메서드를 호출
  4. next()의 반환 값은 {done: Boolean, value: any}와 같은 형태이어야 한다. done=true는 반복이 종료되었음을 의미한다. done=false일땐 value에 다음 값이 저장된다.
let range = {
  from: 1,
  to: 5,

  [Symbol.iterator]() {
    this.current = this.from;
    return this;
  },

  next() {
    if (this.current <= this.to) {
      return { done: false, value: this.current++ };
    } else {
      return { done: true };
    }
  }
};

for (let num of range) {
  alert(num); // 1, then 2, 3, 4, 5
}

이터러블과 유사 배열

  • 이터러블은 Symbol.iterator가 구현된 객체
  • 유사배열은 인덱스와 length 프로퍼티가 있어서 배열처럼 보이는 객체

이터러블이라고 해서 유사 배열이거나 유사배열이라고 이터러블인 것은 아니다.

Array.from() 는 이터러블이나 유사배열을 받아 진짜 배열을 만들어준다.

위크맵, 위크셋

객체의 프로퍼티나 배열의 요소, 맵과 셋의 구성 요소들은 도달가능한 값으로 가비지 컬렉션이 되지 않는다. 맵에서 객체를 키로 사용한 경우도 가비지 컬렉터의 대상이 되지 않는다.

let john = { name: "John" };

let map = new Map();
map.set(john, "...");

john = null; // 참조를 null로 덮어씀

// john을 나타내는 객체는 맵 안에 저장되어있습니다.
// map.keys()를 이용하면 해당 객체를 얻는 것도 가능합니다.
for(let obj of map.keys()){
  alert(JSON.stringify(obj));
}

alert(map.size);

위크 맵은 키로 쓰인 객체가 가비지 컬렉션의 대상이 된다.

위크 맵을 사용하려면 위크맵의 키가 반드시 객체여야한다. 위크 맵의 키로 사용된 객체를 참조하는 것이 아무것도 없다면 해당 객체는 위크맵에서 자동으로 삭제된다.

let john = { name: "John" };

let weakMap = new WeakMap();
weakMap.set(john, "...");

john = null; // 참조를 덮어씀

// john을 나타내는 객체는 이제 메모리에서 지워집니다!

구조분해 할당

  • 할당 연산자 우측에 모든 이터러블이 올 수 있다.

0개의 댓글