그저 내가 되었고

항해99) 2주차:: 프로그래밍 기초; JavaScript for Node.js START!!! 본문

개발/항해99 9기

항해99) 2주차:: 프로그래밍 기초; JavaScript for Node.js START!!!

hyuunii 2022. 9. 23. 21:32

What to do:

주특기 언어와 친숙해지기 & 알고리즘 문제 맛보기


목표 점차 난이도를 올려가며 구현력을 키우는 것

  • 알고리즘 문제와 더불어, 주특기와 친해지기 위한 기본 과제를 해결해보자!
  • 언어의 기초 다지기! 언어를 공부하고 알고리즘 문제를 풀어보자!

 


TIL

1. JavaScript의 자료형? JavaScript만의 특성? 

  • 느슨한 타입(loosely typed)의 동적(dynamic) 언어 👉🏻JS의 변수는 어떤 특정 타입과 연결되지 않으며, 모든 타입의 값으로 할당 및 재할당 가능하며, 컴파일 과정 없이 실행과 동시에 해석하는 '인터프리터 언어'임.
  • JavaScript 형변환(type conversion) 👉🏻JS는 다이내믹한 유연한 언어. 때문에 자스 엔진이 필요에 따라(연산자 사용시 자연적으로) 암시적변환, 혹은 개발자의 의도에 따라 명시적변환을 실행함. 암시적 변환으로는 산술연산자와 동치비교, 명시적 변환으로는 Object(), Number(), toString(), Boolean()등이 있음. 암시적 형변환을 잘 이용하면 더욱 가독성 있는 코드를 작성할 수 있지만 잘못 생각하면 버그 일으키기 십상(변수의 타입을 미리 선언하지 않고  프로그램이 처리되는 과정에서 자동으로 파악된다? 결국 같은 변수에도 불구하고 상황에 따라 값의 타입이 바뀔 수 있다는 뜻) 
  • ↳정적 타입(Statically typed) vs 동적 타입(Dynamically typed): 컴파일 시 변수의 타입이 결정되는 언어. 변수에 들어갈 값의 형태에 따라 프로그래머가 직접 변수 타입 명시해줘야됨. 컴파일 시 자료형에 맞지 않는 값이 들어가면 컴파일 에러 발생. Java, C, C++ 등(e.g. int num=0819) vs 컴파일이 아닌 런타임때 자료형을 정함. 타입 없이 변수만 선언하여 값을 지정할 수 있음. Python, JavaScript, Tuby 등등
  • ==, === 👉🏻동등 연산자 vs 일치 연산자. 일치 연산자는 자료형까지 엄격하게 비교하며, 형변환을 야기하지 않음.
  • 느슨한 타입(loosely typed)의 동적(dynamic) 언어의 문제점은 무엇이고 보완할 수 있는 방법에는 무엇이 있을지? 👉🏻실행 도중 변수에 예상치 못한 타입이 들어와 타입 에러가 발생할 수 있음. 또한 런타임 시 확인하므로 코드가 길고 복잡할 경우 타입 에러를 찾기가 힘듦. 개선 방안으로 타입스크립트(JS에서 코드를 입력할 때 타입을 미리 부여하는 기능을 추가한 정적 타입 언어) 사용할 수 있음. 하지만 컴파일시 타입 명시가 필요 없어 속도가 빠르다는 장점도 있음. 
  • undefined와 null의 미세한 차이들을 비교해보자. 👉🏻둘 다 원시값이란 점에선 동일. undefined는 변수 선언 자체는 되었으나 값이 존재하지 않음/할당되지 않음을 의미. null 역시 변수 선언 자체는 되었으나 빈 값을 할당한 상태. null과 undefined를 동등 연산자인 ==로 비교해보면 자료형 비교까지 이루어지지 않기 때문에 true를 반환, 벗 자료형까지 엄격하게 검사하는 일치 연산자인 ===를 써보면 null과 undefined의 자료형이 다르기 때문에 false가 반환됨.
  • ↳자료형(변수 타입): 값은 항상 문자열이나 숫자형 같은 특정한 자료형에 속함. 숫자형, 문자형, 불린형, null값, undefined값, 객체(object)와 심볼. typeof 연산자로 확인 가능.

 

 

2. JavaScript 객체와 불변성? 

  • 기본형 데이터와 참조형 데이터
    • 👉🏻기본형(Primitive type)[논리형(boolean), 정수형(int), 실수형(double), 문자형(char)]과 . 기본형에는 바로 값을 그대로 할당. 얘는 불변값인데, 뜻은 한 번 만든 값을 바꿀 수 없다는 것. 응?! 그럼 만약 변수 영역에 저장된 값을 변경하고싶으면? 데이터 영역에서 새로 만들고 거길 연결함! 한 번 만들어진 값은 가비지 컬렉팅을 당하지 않는 한 영원히 변하지 않음....!!ㄷㄷㄷ
    • 👉🏻참조형(Reference type) [배열(Array), 클래스(Class), 인터페이스(Interface)]. 기본형의 데이터 집합이라고 볼 수 있음. 얘의 변수는 실제 데이터가 저장된 주소를 참조하기에 참조(reference) 타입이라 불림. 얘는 가변값인데, 데이터를 변경하려 하면 데이터 영역의 저장된 값은 모두 불변값이나 변수에 얼마든지 다른 값을 대입할 수 있기 때문에 그럼(데이터 자체가 아닌 내부 프로퍼티를 변경)(참조형 데이터에서 객체 내부 프로퍼티를 변경? 가변, 참조형 데이터에서 객체 자체를 변경? 불변)
    • 👉🏻둘의 가장 큰 차이점은 실제 값 전체 복사 vs 실제 값이 들어있는 주소 값 복사 & '객체의 변수(프로퍼티) 영역' 의 존재 여부 차이
  • 불변 객체(Immutable Object)를 만드는 방법 ⭐ 👉🏻일단.. 얘는 왜 필요? 객체에 변화를 가해도 원본이 그대로 남아있어야 하는 경우가 있기 때문(e.g. 정보가 바뀌었으면 알림 전송하는 경우, 바뀌기 전의 정보와 바뀐 후의 정보를 보여줘야하는 경우 등) 한번 객체가 생성되면 변하지 않는다는 것. 그래서 객체 내부 프로퍼티를 변경할 때마다 새로운 객체를 만들어 재할당하기로 정하거나 자동으로 새로운 객체를 만드는 도구를 활용하여 (ex. immutable.js, immer.js 등의 라이브러리) 불변성 확보. 만드는 방법은 두 가지로 const와 Object.freeze()가 있음. const 키워드는 변수를 상수로 선언할 수 있음. 
  • 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy) 👉🏻전자는 객체를 복사할 때 해당 객체'만' 복사하여 새 객체를 생성함. 복사된 객체의 인스턴스 변수는 원본 객체의 인스턴스 변수와 같은 메모리 주소를 참조하기에 해당 메모리 주소의 값이 변경되면 원본 객체 및 복사 객체의 인스턴스 변수 값은 같이 변경된다. 후자는 객체를 복사 할 때 해당 객체와 인스턴스 변수까지 복사하는 방식. 전부를 복사하여 새 주소에 담기 때문에 참조를 공유하지 않음.

 

 

3. 호이스팅과 TDZ는 무엇일까?

  • 스코프, 호이스팅, TDZ 👉🏻
    • 스코프? 변수, 함수, 클래스가 접근할 수 있는 유효 범위
    • 호이스팅? 모든 선언들을 모두 끌어 올려서 해당 유효 범위(스코프)의 최상단에 선언하는 것. 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것처럼 행동
    • TDZ? Temporal Dead Zone. 일시적 사각지대. let 또는 const로 변수를 선언했을 때, 선언 이전에 식별자를 참조할 수 없는 구역. 호이스팅으로 변수의 선언이 이루어졌지만 변수의 초기화가 이루어지지 않은 지점, 변수를 참조할 수 없는 지점!!
  • 함수 선언문과 함수 표현식에서 호이스팅 방식의 차이
    • 👉🏻함수 선언식: 함수 전체를 호이스팅. 정의된 범위의 맨 위로 호이스팅되서 함수 선언 전에 함수를 사용할 수 있음.
    • 👉🏻함수 표현식: 별도의 변수에 할당하게 되는데, 변수는 선언부와 할당부를 나누어 선언부만 호이스팅.
  • let, const, var, function 실행 방식 👉🏻
var : 변수 재선언 가능
const, let : 변수 재선언 불가능

const : 변수 재할당 불가능 (상수)
let : 변수 재할당 가능

var : functional-scope 로 호이스팅됨
const, let : block-scope 로 호이스팅됨
  • 실행 컨텍스트  👉🏻
  • 콜 스택 👉🏻
  • 스코프 체인 👉🏻스코프에 식별자가 없을 때 상위 스코프에서 다시 찾아 나가는 현상을 말함. 스코프가 중첩되어있는 모든 상황에서 발생.
  • 변수 은닉화 👉🏻외부 객체로부터 '속성 값(데이터, 멤버 변수값)'을 감추는 특성

 

 

4. 실습 과제

- 콘솔에 찍힐 b 값을 예상해보고, 어디에서 선언된 “b”가 몇번째 라인에서 호출한 console.log에 찍혔는지, 왜 그런지 설명해보자. 주석을 풀어보고 오류가 난다면 왜 오류가 나는지 설명하고 오류를 수정해보자. 

let b = 1;
function hi () {
	const a = 1;
	let b = 100;
	b++;
	console.log(a,b);  //👉🏻const,let는 블럭 스코프에서 유효하기 때문에 함수 내부에 있는 변수들에 접근해서 출력됨

}

console.log(a);  //👉🏻여기서 오류가 나는 이유는 전역적으로 a라는 변수가 존재하지 않아서(해결: 전역적으로 a 초기값 변수를 할당)
console.log(b);  //👉전역 b변수에 접근해서 출력
hi();
console.log(b);  //👉전역 b변수에 접근해서 출력

 

- 두 값이 다른 이유를 설명해보자. 👉🏻숫자 1과 문자 1이기에 자료형까지 보는 일치 연산자는 다르게 판단.

1 == "1";
1 === "1";