자바스크립트의 독특한 특징중 하나는 변수를 만드는 데에 있다. 우선 자바스크립트는 변수 선언이라는 과정이 존재한다. 이 과정은 두 단계에 거쳐 이루어진다.
Variable Hoisting : 소스코드의 평가과정
변수선언의 실행시점은 런타임에 의존하지 않고 그 이전 단계에 먼저 실행된다. 구체적으로, 자바스크립트 엔진은 소스코드를 순차적으로 읽기 전에 소스코드 평가과정을 거친다. 이때 엔진은 변수 선언을 포함한 모든 선언문을 소스코드에서 찾아내어 먼저 실행한다.
console.log(score); // undefined
var score = 80:
console.log(score); // 80
앞서 변수선언이 먼저 필요하다고 했지만, 이는 엔진의 관점에서다. 우리는 var score -> score = 80 과 같은 두번의 과정을 거칠 필요 없이 var score = 80;과 같이 실질적으로 코딩한다. 이때 앞뒤로 로그를 찍어보면, score 코드 이전에 작성된 로그에서의 반응은 undefined를, 이후에는 80을 출력한다. 바로 이해가 갈 듯 싶다. 호이스팅에서 먼저 score 변수선언이 완료되고 그 후 소스코드를 한줄 씩 읽게 되면서 변수에 값이 할당되는 것을 간접적으로 보여준다.
Garbage collector : 메모리 누수 방지, 메모리 공간 검사기
만약 변수 score가 다음과 같은 순서로 undefined, 80, 90 순으로 바뀌었다면 메모리에는 undefined, 80, 90 값이 모두 들어있을 것이며 최종적으로는 90에 식별자(score)가 연결되어 있을 것이다. 이전의 두 값은 불필요해지므로 가비지 콜렉터에 의해 자동 해제된다. 그 시점은 예측할 수 없다.(굳이 파고들지 말자는 뜻인듯.) 근데 알아보았다. MARK & SWEEP의 알고리즘을 기반으로 garbage collection을 진행한다는 것 인데, 루트로 지정된 객체(ex.실행 함수의 전역 변수나 전역 객체)를 시작점으로 각 객체가 참조하는 다른 객체들을 재귀적으로 마킹하고 마킹되지 않는 객체들이 가비지 컬렉션의 대상이 되는 것이 기본 개념
프로그래밍 언어는 메모리 관리 방식에 따라
unmanaged
vsmanaged
로 나뉜다. 바로 느낌이 오겠지만 자바스크립트는 매니지드다. 가비지 콜렉터에 의해 자동관리 되고 있기 때문이다.( C는 아님 )
웹 프로그래밍을 미리 해본 입장에서 세미콜론 작성에 대한 습관이 없어, 작성하지 않고 실행해본 경우가 많았는데 문제가 된 적이 크게 기억나지 않았다. 이런 기능이 엔진안에 포함되어 있기 때문이었다. 하지만 간혹 자동 삽입 기능과 개발자의 예측이 일치하지 않는 경우 문제가 발생할 수 있다.
정적 타입 언어는 변수를 선언할 때 변수의 타입을 사전에 선언해야한다. 예로 C의 경우 int num;이라는 변수를 선언한다는 것은 정수 타입의 값만 할당할 수 있다. 만약 num = 1.3이 할당된다면, 컴파일 시점에 타입 체크 과정에서 에러를 발생시킨다.(C, Kotlin, C++ 등등)
반면 자바스크립트나 파이썬과 같은 동적 타이핑 언어는 변수 선언이 아닌 할당에 의해 타입이 결정된다(type inference) 역시 재할당에 의해 타입또한 자동적으로 변화한다. 유일하게 객체가 아닌 것이 데이터 타입
이다. 변수는 타입을 가지지 않는다. 값은 타입을 가진다. 이런 기능은 데이터 타입에 무감각해질 정도로 편리한 장점을 가진다. 하지만 구조적인 단점또한 존재한다. 개발자의 의도와 다르게 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환될 수 있다.
실제 프로그래밍시
실제 프로그래밍시 데이터베이스에서 숫자라고 생각한 데이터를 뽑아 숫자 데이터 타입처럼 다루었다면, 에러가 발생할 것이다. 우리는 데이터베이스로부터 나와 처리되는 과정 모두를 검사해야 할지도 모른다.
- 변수는 꼭 필요한 경우에 한해 제한적으로 사용하자
- 변수의 유효 범위(스코프)를 최대한 좁게 만들어 부작용을 대비하자.
- 전역 변수는 최대한 사용하지 않는다.
- 변수의 특성이 필요없다면, 변수보다는 상수를 사용해 값의 변경을 억제하자.
- 변수 이름을 규칙에 따라 잘 네이밍하자.
프로그래밍시에 중요한 것이 만들어진 규칙을 지키는 것이다. 이는 다른 코드를 읽을 때에도 자신이 자신의 소스코드를 다시 검토할 때에도 가독성의 측면에서 중요하다. 이에 따라 처음부터 네이밍 컨벤션을 잘 지켜서 습관화해두면 다른 프로그래머와 소통할 때에도 혼자 작업할 때에도 편리하다. 여러가지 케이스가 존재하나 주로 사용하는 두 케이스만 잘 숙지해서 습관하하자.
기본적으로 두 단어를 합쳤을 때 두번째 단어의 첫 글자만 대문자로 바꾸는 것이 카멜케이스이고, 세 단어를 합쳤을 때에는 첫번째 단어만 제외하고 나머지 단어들의 첫 글자를 대문자로 바꾸어 준다. 주로 변수와 함수 이름에 사용한다
카멜케이스와 비슷하지만, 첫 단어의 첫글자 까지 대문자로 바꾸어주는 것이 파스칼 케이스이다 생성자 함수, 클래스 이름에 사용한다
var x = 5, result;
result = x++;
console.log(result, x) // 5, 6
++
과 --
에 대해 설명하도록 하겠다. 둘은 증가, 감소 연산자로 x++처럼 사용하기도 하고, ++x 처럼 사용하기도 한다. 위의 예시는 ++를 피연산자 뒤에 배치했다. 피연산자를 기준으로 연산자의 위치에 따라 증가라는 행동의 순서를 결정할 수 있다. 위의 코드를 그대로 해석하면, 우선 x와 result라는 변수를 선언한다. 그 후 x에 5를 할당한다. 그 다음, result에 x를 할당한다 그 후 ++에 의해 x는 1이 증가한다. 그 결과 로그를 찍어보면 result는 5, x는 6이 된다. 만약 ++를 x앞에 두었다면 result에 x가 할당되기 이전에 x가 먼저 증가연산이 이루어지므로 result와 x는 둘다 6,6이 될 것이다.
연산에서 암묵적 타입 변환이 일어날 때가 있다. 바로 boolean type을 다룰 때 이다. 1 + true 의 예시를 보면 좋다. 답은 2인데, true는 숫자로는 1로 치환될 수 있기 때문이다. 이러한 절차를 따로 타입을 바꿔주는 직접적인 작업 없이 JS엔진은 이를 자동적으로 수행해준다.(boolean to numeric)
==(동등비교)
vs ===(일치비교)
로 예시를 들어 설명하겠다. x == y
는 x와 y의 값이 같으면 true를 결과로 줄 것이다. 이때 값의 같음에 대한 비교는 암묵적 타입 변환을 통해 우선적으로 타입에 상관없이 일치하면 true를 준다. 반면 x===y
의 경우에는 타입까지 똑같아야 한다. 더 엄격한 룰이다. 엄격하지만 생각해보면 암묵적 타입 변환같은 과정이 필요없기에 더 우수한 비용을 가질 것으로 생각한다.
예시로 5 == '5' 는 true이며 5 === '5'는 false이다.
var result = score >= 60 ? 'pass' : 'fail';
// 만약 score가 60 이상이면 pass
// score가 60 미만이면 fail
형식에 익숙해질 필요가 있을 것 같다. true일때 반환할 것과 false일때 반환할 것은 :
로 연결하며 ?
의 위치와 조건문의 위치에 익숙해져야한다. result = 조건문 ? true : false;의 문법형식에 익숙해지자.
짜잘한 바로 알기 쉬운 것들에 대해서는 작성하지 않았다. 예를 들어 예시문제나 간단한 연산자에 관해서는 작성하지 않았다. 이 글은 모던 자바스크립트 Deep Dive에서의 1~7장을 다루며, 나에게 필요한 작성 가치가 있는 것들만 담았다.