Chapter 3. 타입, 값, 변수

허상범·2022년 12월 26일
1
post-thumbnail

자바스크립트 완벽 가이드 7판 스터디
책의 목차를 따라가며 관련 내용을 학습하고 공유하는 스터디입니다.

이 장에서 기억해야 할 핵심은 다음과 같습니다.

  • 자바스크립트에서 숫자와 문자열을 만들고 조작하는 법
  • 자바스크립트법의 다른 기본 타입인 불, 심벌, null, undefined를 다루는 법
  • 불변인 기본 타입과 가변인 참조 타입의 차이
  • 자바스크립트가 묵시적으로 타입을 변환하는 과정, 그리고 프로그램에서 직접 변환하는 법
  • 상수 변수를 선언하고 초기화하는 법(분해 할당 포함), 선언하는 변수와 상수의 어휘적 스코프

자바스크립트 완벽 가이드 7판, p.68

1. 데이터 타입 분류
2. Number Type
3. String Type
4. Boolean Type
5. null, undefined
6. 타입 체크
7. 타입 변환
8. 변수 선언과 할당
9. let, const
10. Scope, Scope Chain
11. 호이스팅
12. 구조 분해 할당


1. 데이터 타입 분류

  • 자바스크립트 데이터 타입은 크게 두 가지로 분류 Primitive(기본형) & Reference(참조형)
  • 기본형과 참조형은 각 데이터가 메모리상에서 저장되는 형태에 차이가 있다.

Primitive(기본형)

  • Number, String, Boolean, null, undefined, Symbol, BigInt

Reference(참조형)

  • === Object
    • Array, Function, RegExp, Set, Map, Date

2. Number Type

IEEE754로 규정된 64비트 부동소수점으로 숫자를 표현

  • 표현방식: 부호(1비트), 가수부(11비트), 지수부(52비트) = 64비트
  • c, java 같은 다른 언어와 달리 number 타입 하나만 있음
  • 정수, 실수, 음수, 2진수, 8진수, 16진수 표시 가능
  • _ 구분자 사용 가능
console.log(Number(123));
const integer = 789; // 789 (정수)
const negative = -789; // -789 (음수)
const double = 7.89; // 7.89 (실수)
const binary = 0b1101; // 13 (2진수)
const octal = 0o733; // 475 (8진수)
const hex = 0x6b; // 107 (2진수)
const splited = 1_000_000; // 1000000

NaN (Not a Number)

  • 숫자가 아닌 값
  • 숫자로 표현할 수 없을 때의 값
  • 자기 자신을 포함해 어떤 값과도 같지 않음
  • NaN을 확인하기위해서는 isNaN을 사용
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
console.log(789 / 'code'); // NaN
console.log(0 / 0); // NaN
console.log(Infinity / -Infinity); // NaN

const nan = 789 / 'code';
console.log(isNaN(nan)); // true

const study = Number('스터디'); // 문자열 '스터디'를 숫자형으로 변환 시도
console.log(study); // NaN

0, -0, Infinity, -Infinity

  • 자바스크립트가 표현할 수 있는 가장 큰 숫자보다 큰 경우 Infinity 반환
  • 자바스크립트가 표현할 수 있는 가장 큰 작은보다 작을 경우 -Infinity 반환
  • 0-0은 같다.
console.log(0 === -0); // true
console.log(Infinity / -Infinity); // false
console.log(1 / 0); // Infinity
console.log(1 / -0); // -Infinity

BigInt

  • Number 원시 값이 안정적으로 나타낼 수 있는 최대치인 2^53 - 1보다 큰 정수를 표현할 수 있는 내장 객체
  • BigInt는 정수 리터럴의 뒤에 n을 붙이거나(10n) 함수 BigInt()를 호출해 생성
  • 내장 Math 객체의 메서드와 함께 사용할 수 없음
  • 연산에서 Number와 혼합해 사용불가, 따라서 먼저 같은 자료형으로 변환해야
const theBiggestInt = 9007199254740991n; // 9007199254740991n
const alsoHuge = BigInt(9007199254740991); // 9007199254740991n
console.log(theBiggestInt === alsoHuge); // true
console.log(theBiggestInt + alsoHuge); // 18014398509481982n
console.log(theBiggestInt + 789); // TypeError: Cannot mix BigInt and other types, use explicit conversions

자주 사용하는 메소드

// 0이상 ~ 1미만의 랜덤한 숫자
console.log(Math.random());

// 최대값, 최소값
console.log(Math.max(5, 10, 3)); // 10
console.log(Math.min(5, 10, 3)); // 3

// 올림, 반올림, 내림, 소수점 아래 자르기
console.log(Math.ceil(-3.3)); // -3
console.log(Math.round(-3.4)); // -3
console.log(Math.floor(-3.7)); // -4
console.log(Math.trunc(-3.7)); // -3

// 절대값
console.log(Math.abs(-5.5)); // 5.5

// -1, 0, 1 반환
console.log(Math.sign(-123)); // -1
console.log(Math.sign(0)); // 0
console.log(Math.sign(123)); // 1

// 1 ~ 9 중에 뽑기
console.log(Math.floor(Math.random() * 10));

부동 소수점 계산 오류

  • 'e'를 쓸 때 주의
  • 연산할 때 주의
  • 0.1 + 0.1 === 0.2가 아닌 이유
  • 그럼 에러 방지 방법은?

3. String Type

(")큰따옴표, (')작은따옴표, (`)백틱으로 둘러싸인 문자의 집합

  • 16비트 값이 순서에 따라 이어진 형태
  • 문자 하나를 나타내는 타입은 따로 없음
  • 각 값은 일반적으로 유니코드 문자
  • 문자열에 포함된 16비트 값의 개수를 나타내는 length 프로퍼티를 갖음
const str1 = "큰따옴표 안에 '작은따옴표' 있다";
const str2 = '작은따옴표 안에 "큰따옴표" 있다';
const empty_string = '';
const length = 'abcd'; // 4

문자열 병합

const a = 'str';
const b = 'ing';
console.log(a + b); // string
console.log(a.concat(b)); // string

문자열 비교

동등비교 ==, === 사용

const str = '123';
const num = 123;

console.log(str === num); // false
console.log(str == num); // true

크기비교

  • 문자열의 크기 비교는 다른 언어와 동일하게 ASCII 값을 비교하여 크기를 결정
  • 알파벳 순서가 앞에 있을 수록 더 크기가 작으며, 문자열의 앞에서 뒤의 순서대로 비교
  • 문자열이 길어도 같은 위치(Index)의 문자의 알파벳 순서가 작다면 문자열의 크기가 작다고 계산
  • 문자열 길이가 짧아서 같은 Index에 문자가 없으면 더 작은 문자열로 계산
const str1 = 'abcd';
const str2 = 'ab';
const str3 = 'abd';
const str4 = 'aba';
const str5 = 'bbcd';

console.log(str1 > str2); // true
console.log(str1 < str3); // true
console.log(str1 > str4); // true
console.log(str1 < str5); // true

템플릿 리터럴

  • 자바스크립트 표현식을 넣을 수 있음
  • ${} 가로 안에 표현식을 넣음
  • 표현식을 평가해 그 값을 문자열로 변환
const today = new Date();
const templated = `오늘 날짜: ${today}`;
console.log(templated);

이스케이프 시퀀스

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String#%EC%9D%B4%EC%8A%A4%EC%BC%80%EC%9D%B4%ED%94%84_%ED%91%9C%ED%98%84
mdn

  • 특수 문자는 이스케이프 표현을 사용해 표현 가능
const stringWithEscape = 'Hello\nWorld!!\t\t\tCode\\\u005C';
console.log(stringWithEscape);
// Hello
// World!! Code\

APIs

  • 문자열 자르기: substring, slice, split
  • 검색: indexOf, lastIndexOf, startsWith, endsWith, includes, charAt
  • 변경: replace, toLowerCase, toUpperCase
  • 반복: repeat
  • 공백 제거: trim, trimStart, trimEnd
  • 스페이스 추가: padStart, padEnd

4. Boolean Type

  • 참, 거짓 두 가지 값
  • 모든 값은 불리언 값으로 변환 가능 - !! 사용
let= true;
let 거짓 = false;
console.log(); // true
console.log(거짓); // false

Truthy한 값 & Falshy한 값

값이 없거나 0, -0, null, false, NaN, undefined, 빈 문자열 ("")이라면 객체의 초기값은 false가 됩니다.
문자열 "false"를 포함한 그 외 모든 다른 값은 초기값을 true로 설정합니다.

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Boolean#%EC%84%A4%EB%AA%85

console.log(!!0, !!-0, !!null, !!false, !!NaN, !!undefined, !!''); // 전부 false
console.log(!!123, !!-123, !![], !!{}, !!' ', !!-Infinity, !!'str'); // 전부 true

Boolean 값 비교

  • 묵시적 형변환
    • true1
    • false0
console.log(true > false); // true (1 > 0)
console.log(true == false); // false (1 == 0)
console.log(true < false); // false (1 < 0)
console.log(true == 1); // true
console.log(false == 0); // true

5. null, undefined

undefined

  • 값을 할당하지 않은 변수, 아직 아무 것도 정해진 것이 없는 상태
  • 메서드와 함수의 인자가 평가할 값을 할당받지 않은 경우에 undefined를 반환
  • 함수는 값을 명시적으로 반환하지 않으면 undefined를 반환
  • undefined는 예약어가 아니기 때문에 식별자로 사용가능 => 사용 X

null

  • 값이 없다는 값을 표현
  • 값이 없다는 값을 할당할 때는 undefined 대신 null을 사용하는 것이 좋다.
let value;
console.log(value); // undefined

value = null;
console.log(value); // null

console.log(typeof undefined); // undefined
console.log(typeof null); // object

6. 타입 체크

  • 변수는 할당된 값에 따라 타입이 결졍된다.
    • 변수를 선언할 때 타입을 지정하고 해당 타입에 맞는 값을 할당하는 언어와 차이

typeof

  • 데이터 타입을 확인해 문자열로 반환
console.log(typeof 123); // number
console.log(typeof NaN); // number
console.log(typeof 'str'); // string
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined

console.log(typeof null); // object
console.log(typeof [1, 2, 3]); // object
console.log(typeof { 1: 'one' }); // object

// 배열 체크
console.log(Array.isArray([1, 2, 3])); // true

7. 타입 변환

  • 자바스크립트는 타입을 강제하지 않는다.
  • 경우에 따라 필요에 맞게 값/타입을 변환한다.
  • 책의 표 3-2 참고

명시적 변환

  • Number(), String(), (Boolean(), !! , +
  • toString() valueOf() : 대부분의 자료형에 내장
console.log(typeof Number('123')); // number
console.log(typeof String(123)); // string
console.log(Boolean(123)); // true
console.log(!!0); // false;

console.log(typeof +'111'); // number

묵시적 변환

  • 함수와 연산자에 전달되는 값은 대부분 적절한 자료형으로 자동 변환
console.log(typeof (2 - '1')); // number (1)
console.log(typeof (2 * '111')); // number (222)
console.log(typeof (2 / 'a')); // number (NaN)

if (1) {
  console.log(true);
} else if (0) {
  console.log(false);
}

8. 변수 선언과 할당

변수 Variable

  • 값을 저장하는 공간
  • 자료를 저장할 수 있는 이름이 주어진 기억장소
  • var, let, const
// let a = 1;
let a; // 변수 선언 : let은 키워드, a는 변수이름 또는 식별자
a = 1; // 할당: 변수 a에 값 1 할당, =는 할당연산자
a = 10; // 재할당: 변수 a에 값 2 재할당

기본형 데이터 할당의 기본적인 순서

실제 자바스크립트 메모리 구조가 이렇지 않다. 흐름 파악을 위한 설명

  1. 하나의 셀에 각각 주소(1001, 1002 ...)가 부여되어 있다.

  1. book를 선언하면,
  • 데이터가 담길 임의의 공간 1002을 확보
  • 확보한 공간의 이름에 식별자 book를 지정
  1. 문자열 guidebook에 할당하면,
  • guide를 우선 비어있는 메모리 공간에 저장(5002)
  • 변수 book가 가리키는 주소로 이동
  • 주소1002의 값을 5002로 지정
  1. 문자열 Definitivebook에 재할당하면,
  • 별개의 문자열로 새로운 주소(5003)에 값을 지정
  • book를 찾아서 값을 5005로 변경함

기본형 데이터가 불변인 이유

같은 값이 오직 하나만 존재한다.

  • 동일한 문자열 자바스크립트 완벽 가이드가 두 곳에 할당되어 있음
  • 문자열를 각각 다른 주소에 저장한다면
    • study.title === study.books[0] => 비교하는데 오래 걸림
    • 만약 동일한 문자열을 1000개 저장한다면?
    • 데이터 할당시에는 빠름
    • 비교에 비용이 많이 듬
    • 메모리 낭비가 심함
  • 동일한 문자열을 하나의 주소에 저장한다면
    • 할당하는데 더 오래 걸림 => 동일한 문자열이 있는지 찾아야함
    • 데이터 할당시에는 느림
    • 비교에 비용이 들지 않음
    • 메모리 낭비가 최소화

같은 값이 메모리 상에 오직 하나만 존재한다는 의미 => 불변값


참조형 데이터 할당의 기본적인 순서?

  • 객체할 떄 같이 알아보기? (객체 복사 등과 같이)

9. let & const

  • ES6에서 추가
  • 유효범위: 블록 스코프 (var는 함수 스코프)
  • let : 재할당 가능
  • const : 재할당 불가능
    • 상수, 상수변수, 변수라고 부른다
  • 작성할 때 되도록이면 const 사용 : 불필요한 오류 가능성을 남길 필요가 없음
    • 값이 변경이되는 경우에만 let 사용
let a = 1;
a = 2;

const b = 2;
b = 3; // TypeError: Assignment to constant variable.

// 상수: 대문자로 작성하는 경우가 많음
const API_KEY = '12341234';

// 상수 변수
const man = {
  name: 'Hee',
  age: '10',
};
man = { name: 'Go', age: '20' }; // TypeError: Assignment to constant variable.

man.name = 'Go';
console.log(man); // { name: 'Go', age: '10' };
// 객체 내부 데이터 변경은 가능하다. => 참조형 데이터의 할당에서 같이 봐야함

10. 스코프, 스코프 체인

  • 변수를 참조(접근)할 수 있는 유효한 범위
  • 식별자(변수, 함수, 클래스)가 유효한 범위
  • 이름 충돌 방지, 메모리 절약
  • Block Scope, Function Scope

Block Scope

  • ES6에서 추가
  • class, if문, for문, while문, switch문 ... 문에 적용 (문 === 문단)
  • 문은 결과를 리턴하지 않는다.
  • {...} 자체가 Block Scope가 된다.
const d = 5;

if (true) {
  var a = 1;
  const b = 2;
  let c = 3;
}

console.log(a); // 1
console.log(d); // 5
console.log(b); // ReferenceError: b is not defined
console.log(c); // ReferenceError: c is not defined

let sum = 0;
for (let i = 0; i < 10; i++) {
  sum += i; // {}밖에 있지만 내부에서 동작
}
console.log('sum:', sum); // sum: 45
console.log('i:', i); // ReferenceError: i is not defined

스코프 체인

  • 스코프 체인은 해당 코드의 유효 범위(in scope) 안에 있는 변수를 정의하는 객체의 체인, 리스트다.
  • 자바스크립트가 변수 값을 얻으려고 할 때 스코프 체인에서 변수를 찾는다.
  • 스코프 체인은 위에서 말했다시피 객체의 리스트이므로, 스코프 체인에서 변수를 찾지 못하면 상위 스코프를 탐색한다.
  • 리스트의 끝까지 탐색했는데도 그 변수가 없다면 reference error가 발생하는 것이다.
{
  let a = 10;
  {
    let a = 20;
    console.log(a); // 20 : 현재 스코프에서 찾음
  }
  console.log(a); // 10 : 1단계 위 스코프에서 찾음
}
console.log(a); // ReferenceError: a is not defined : 최상위 스코프까지 탐색헀는데 없음

var 는 블록 스코프에 영향을 받지 않는다. 함수 스코프에 영향

function hasValue(p) {
  if (p) {
    var v = 'blue';
    console.log(v); // blue
  }

  console.log(v); // blue
}

hasValue(true);

11. 호이스팅

  • 자바스크립트 엔진이 코드를 실행하기 전에 변수, 함수, 클래스의 선언문을 끌어올리는 것을 말함
  • 함수 선언문보다 위에서 함수를 호출해도 동작한다.
  • var, let, const 전부 조금씩 방식으로 호이스팅 된다.
// 함수의 선언문 전에 호출이 가능하다.
hello('a'); // Hello a

function hello(name) {
  console.log('Hello ' + name);
}

hello('b'); // Hello b
// apple이 초기화되기 전에 접근할 수 없다.
// apple이 선언되기 전인데 apple을 알고있음 => 호이스팅

// let, const, class는 선언만 호이스팅되고 초기화는 안된다.
// 자바스크립트는 초기화되지 않은 변수에 접근할 수 없다.

console.log(apple); // ReferenceError: Cannot access 'apple' before initialization

let apple = 'iphone';

console.log(apple); // iphone
const apple = 'iphone';
{
  console.log(apple); // ReferenceError: Cannot access 'apple' before initialization
  let apple = 'galuxy';
}

12. 구조 분해 할당 Destructure

  • 쉽게 데이터 그룹화 가능
  • 반복 작업 제거
  • 배열, 객체 파트에서 다시 체크해보기
const person = { nickname: 'aaa', age: 20, job: 'developer' };

const { nickname, age, job } = person;
console.log(nickname, age, job); // aaa, 20, developer

console.log(person.nickname, person.age, person.job); // aaa, 20, developer


참고자료

0개의 댓글