TIL | JS 기초 문법

noopy·2021년 8월 2일
2

TIL

목록 보기
1/21
post-thumbnail

Week 1. 알쏭달쏭한 JS 기초 문법 학습 🔥

JS와 동적타이핑(Dynamic Typing)

JS는 동적타이핑언어이다.
동적타이핑이란, 변수에 타입을 미리 선언할 필요 없이 값을 할당하면 값의 타입에 의해 자동으로 변수에 타입이 정해진다는 뜻이다.

let a = 'text';
// String type 'text'를 a에 할당.
a = 1;
// a에 Number 1을 재할당.

형변환

형변환이란, 다른 타입끼리의 연산이 필요할 때 적절한 자료형으로 자동 변환되거나, 명시적으로 자료형을 변환시킬 때 사용하는 말이다.

✏️ 숫자형 형변환

전달받은 값숫자형 변환 후
undefinedNaN
null0
true, false1, 0
string처음과 끝 공백 제거 👉🏻 제거 후 숫자만 있으면 숫자 반환 or NaN
  • null은 숫자형 변환 시 0

✏️ 불린형 형변환

변환 시 false

  • 빈 문자열, null, undefined, NaN...
  • ⭐️ 숫자 0

나머지 true

  • 문자열 "0"은 true

호이스팅과 클로저

🍡 스코프

  • 함수 레벨 스코프: var로 선언된 변수, 함수 선언식으로 만들어진 함수
    ⭐️ 함수 선언식: function name(parameter) {statements}
  • 블록 레벨 스코프( {} ): let, const로 선언된 변수

🍡 호이스팅

호이스팅: 선언(만)을 끌어올리다.
JS 함수는 실행되기 전 parser가 함수 안에 필요한 변수들을 모아모아 유효 범위(scope)의 최상단에 선언한다. 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다. 다만 실제로 끌어올려지는 것은 아니며 JS Parser가 내부적으로 처리한다고 한다. 따라서 실제 메모리엔 변화가 없다.

{
	name = 'jeongs'; // 변수 선언 전에도 할당 가능
  	var name;
}
console.log(name); // 블럭 밖임에도 접근 가능

var로 선언된 변수는 함수 레벨 스코프이기 때문에, 블록 밖에서도 접근이 가능하다. 또한 var 호이스팅으로 인해 선언 전에도 할당이 가능하다는 무시무시한 유연함이 있다. 😫 함수 선언식으로 생성된 함수도 마찬가지이다.

🍡 클로저

클로저란 내부 함수에서 외부 함수의 지역변수에 접근할 수 있는 함수를 말한다.

function outerFunc() {
	let a = 1;
	function innerFunc() { console.log(a); };
 	return innerFunc; // outer은 return하여 생을 마감함.
}

let inner = outerFunc();
inner(); // 1

함수 outerFunc를 호출하면 내부함수 innerFunc가 반환되고, 함수 outerFunc는 return 후 생을 마감했다. 함수 outerFunc가 생을 마감했기 때문에 지역변수 a도 유효하지 않을거라 생각하지만 내부함수 inner를 통해 여전히 outerFunc의 지역변수 a에 접근가능하다.

은닉화: 외부함수가 생을 마감해도 내부 함수를 통해 외부함수의 지역변수에 접근 가능하므로 그 변수는 private한 변수가 된다! 프로젝트 규모가 커지면 private한 변수를 통해 아무나 수정할 수 없도록 하는 것이 중요하다.

다만, 클로저는 자신이 생성될 때의 환경(Lexical environment)을 기억하므로 메모리가 소모된다. 따라서 클로저 사용이 끝나면 null을 통해 참조를 제거해주자.

메모리 구조와 동작원리

메모리 구조

JS엔진이 JS를 실행할 때, 원시 타입과 참조 타입을 저장하는 메모리 구조로 각각 call stack과 heap을 사용한다.

  • call stack: 원시타입 값과 함수 호출의 실행 컨텍스트를 저장하는 곳
  • heap: 참조타입 값을 저장하는 곳(배열, 객체, 함수 등)

🧐 실행컨텍스트: 코드들이 실행되기 위한 환경

- 굉장히 복잡하기 때문에 나중에 따로 글을 작성해보겠다.


원시타입 값들은 call stack에 잘 쌓여있지만, myArray와 같은 배열은 heap에 생성된 메모리 주소를 참조한다. heap의 메모리 영역은 동적으로 크기가 변할 수 있어서 값이 변해도 heap에 잘 저장된다.

만약 memory heap이 가득차게 되면 어떻게 될까?

Garbage Collector

이를 방지하기 위해 JS엔진은 가비지 컬렉터의 특정 알고리즘으로 메모리를 정리한다.
call stack의 경우, 사용된 변수들은 pop되어 call stack에서 사라진다.
반면 memory heap은 알고리즘을 사용해 더이상 참조하지 않는 데이터를 판별해 지운다.

Mark and Sweep Algorithm

변수가 데이터를 가리키고 있으면 mark하고, 그렇지 않으면 지운다.
브라우저에서 최상위 객체인 window에 시작해 페인트를 붓듯이 천천히 내려가며, 닿지 못한 곳은 지운다.

간단하게 객체로 예시를 들어보자.

let box = {product: 'pencil'};
box = 1;

객체 box가 1이 되며, 기존의 {product: 'pencil'}를 가리키는 변수가 없다.
이 때 가비지 컬렉터의 알고리즘에 의해 {product: 'pencil'}는 조용히 사라진다.

느낀점

기초를 배우고 있지만, 아직 나는 모르는게 너무 많다. 특히 클로저를 공부할 때 JS 구동원리를 빠삭하게 깨우쳐야겠다는 생각이 들었다. 이번 주말에 렉시컬 환경, 실행 컨텍스트 등 구동원리를 공부해 정리해야겠다.

😉 참고한 사이트

profile
💪🏻 아는 걸 설명할 줄 아는 개발자 되기

0개의 댓글