[javascript] var, let 그리고 const

[javascript] var, let 그리고 const

이 포스팅은 사실 [javascript] var가 let보다 빠르다...? 포스팅을 쓰던 중에,

부가설명이 필요해서 var과 let, const에 대한 내용을 별첨으로 정리하던 내용인데...

이게 또 쓰다보니 제법 길어져서 별도 포스팅으로 발행하게 되었습니다.

0. javascript에서 변수를 선언하기

아이들이 마음껏 뛰어놀 수 있는 놀이터처럼,

컴퓨터로 동작하는 모든 시스템은 우리가 흔히 RAM이라고 부르는, 메모리라는 놀이터에서 뛰어놀게 된다.

그리고 이때 시스템이 동작하기 위해선 그 시스템이 활용하는 '값'들이 메모리 한켠에 적재되고, 그 메모리에 적재된 값을 가리키는 변수가 존재하며 개발자들은 그 변수를 사용해서 시스템을 구축하게 된다.

Javascript도 마찬가지로 변수를 정의하는 키워드가 존재한다.

ES6(2015)가 공시된 2015년 이전에는 var이라는 하나의 키워드만 존재했지만,

이때를 기점으로 변수를 정의하는 let과 상수를 정의하는 const라는 키워드가 추가되게 되었다.

변수/상수를 선언하는 방법은 여타 프로그래밍 언어와 크게 다르지않다.

아래와 같은 형식으로 이름을 짓고 그에 맞는 값을 할당하기만 하면된다.

let let_value = "let!"; var var_value = "var!"; const const_value = "const!";

사실 여기까지만해도, 이 3가지 키워드는 크게 차이가 없어보인다.

그냥 변수명 앞에 쓰여서 얘가 변수에요! 라고 선언해주는 역할이니까.

1. var

1-1. 굳이 쓰지않는다면 너는 var이어라

변수를 선언할 때, 굳이 var이나 let, const와 같은 키워드를 쓰지않아도 변수로써 정의된다.

이때 해당 변수는 var로 취급됨과 동시에 전역변수로써 등록된다.

function test(){ num = 10; console.log('num >> ', num); // 10 }

위와같은 코드는 정상적으로 콘솔로그에 10이라는 값을 출력해준다.

1-2. 동명이인도 OK

여타 프로그래밍언어는 동일한 변수명에 대해 선언이 불가능하지만, javascript는 가능하다.

function same_name(){ var num = 10; console.log('num >> ', num); // 10 var num = 20; console.log('num >> ', num); // 20 var num = 30; console.log('num >> ', num); // 30 }

바로 위와같은 형태인데, num이라는 이름을 가진 변수를 3번이나 정의했지만 아무런 에러없이 코드는 잘 실행된다. 다만, 이경우엔 당연하게도 세번째로 정의한 변수가 위의 첫번째, 두번째 변수명을 엎어쳤기 때문에 첫번째와 두번째로 선언한 num이라는 변수는 더이상 코드적으로 접근할 방법이 없으므로 추가적인 활용이 불가능하다.

1-3. function scope

javascript의 var은 function scope를 가진다.

javascript의 함수를 실행하면, 실행 컨텍스트(Execution Context)가 생성되고 이에 따라 동작할 컨텍스트 스택(Context Stack)이 콜 스택(Call Stack)이라는 메모리상의 자료구조에 쌓이게 되는데, 이때 적재되는 스택의 단위는 function이다.

function outer(){ console.log('outer'); function inner(){ console.log('inner'); } inner(); } outer();

그래서 위와 같은 코드를 실행하게 되면, 대략 아래와 같은 순으로 실행 컨텍스트에 따라 Javascript가 동작하게 된다.

그리고 여기서 javascript가 'function'을 기준으로 동작한다는 매커니즘'에 기반해서 생각해보면, javascript의 태생부터 존재했던 var이라는 변수 선언 키워드의 scope도 동일하게 function scope라는 부분이 이해가 될 것이다.

한 문장으로 요약하자면,

javascript는 function을 기준으로 동작 하니까, javascript의 변수 선언 키워드인 var도 function scope.

그래서 아래와 같은 예시를 생각해보면,

function scope_var(){ // 코드 출처 : https://poiemaweb.com/js-scope var x = 'global'; function foo() { var x = 'local'; console.log(x); // local function bar() { console.log(x); // local } bar(); } foo(); console.log(x); // global }

x 라는 변수를 함수 여기저기에 활용하며 function scope의 예시를 보여주는 코드이다.

주의깊게 봐야 할 부분은 bar function 내부에서 사용한 x라는 변수다.

x는 bar function 내부에서는 선언되지 않았지만, bar function 이 선언된 foo function 내부에 선언된 변수이기 때문에 foo function 안에 함께 정의된 bar function 내에서의 x는 foo function 이 가지는 scope를 기준으로 x를 가져와서 사용하게 된다(이러한 형태를 스코프 체인(Scope Chain)이라고도 한다)

이와같이 var로 선어한 변수는 function을 기준으로 scope를 가지게 된다.

2. let

2-1. Block Scope

C나 C++, JAVA와 같은 오래된 연식(?)의 프로그래밍언어에서의 변수들은 block scope를 가진다. 그리고 이를통해 개발에 입문한 (나와같은)사람들은 변수는 block scope를 가진다는 개념이 머릿속에 정립되어있기 때문에, javascript에 입문할 때 var가 가지고 있는 function scope 개념이 굉장히 헷갈리곤한다.

그래서인지 ES6(2015)에 let이라는 변수 선언용 키워드가 추가되었는데,

이 키워드는 var과는 다르게 block scope를 가지고 있다.

4. 동적 타이핑(Dynamic typing)

Javascript의 변수 선언방식이, 기존 프로그래밍 언어들과 다른점은 변수의 자료형을 가리지않는다는 것이다.

// javascript var num_value = 42; // number var str_value = "str"; // string var bool_value = true; // boolean

이러한 특성은 var뿐만 아니라 let, const도 동일하게 가지고 있는 점으로써, 위 코드에서 대입 연산자(=)를 통해 바인딩되는 값들의 타입은 number, string, boolean으로 전부 다르다. 하지만 var이라는 키워드를 통해 변수를 선언하는 부분은 동일한데, 이는 변수의 타입을 키워드로 특정짓지않아도 프로그램이 동작할 때 자동으로 해석해준다는 것이다.

예를들어, JAVA라면 위와 같은 변수들을 각각 선언할 때 아래와 같이 키워드를 구분해서 써줘야한다.

(아래 코드 중 JAVA의 String은 객체지만, 동일 형태의 데이터 타입 비교를 위해서니 양해바랍니다)

// java int num_value = 42; // number String str_value = "str"; // string boolean bool_value = true; // boolean

이와같은 개념을 Javascript에서는 동적 타이핑(dynamic typing)이라고 정의하고있으며, 이는 Javasript가 느슨한 언어(loosely typed) 혹은 동적 언어(dynamic language)라는 개념에 근간을 두고있기 때문이다.

5. 호이스팅

4. 차이점에 대하여

1. const는 상수다.

최초에 선언한 이후로, 변하지 않는 수를 우리는 상수라고한다.

let과 var는 선언때 할당한 값을 이후에 변경가능하지만, const는 선언과 동시에 할당된 값을 바꿀 수가 없다. 그렇기에 let과 var는 '변수'를 선언하는 역할이고 const는 '상수'를 선언하는 역할이다.

const name = 'Grey'; name = 'Ren';

만약 위와같이, 상수로 정의한 name의 값을 변경하려한다면 아래와 같은 콘솔 에러를 확인할 수 있으며

const에 할당된 값을 변경하려 했을 경우

이는, 말그대로 상수(constant variable)를 변경하려했기 때문에 발생하는 에러이다.

또한 const는 상수이기 때문에 아래와 같이 값을 할당하지 않는 것도 에러이다.

const name;

const에 값을 할당하지 않았을 경우

2. 호이스팅

var와 let, const로 선언한 변수/상수는 Javascript 실행시 호이스팅되지만,

var는 호이스팅때 undefined로 초기화되고 let과 const는 uninitialized로 초기화된다.

이에 대한 상세한 설명을 여기서 다루기엔 너무 주제를 벗어나기에 우선 저렇게 알아주기를 바라며...

혹시나 왜 그런지 궁금하신 분은 내가 작성했던 또 다른 포스팅인 [Javascript] class도 호이스팅이 되나요(feat. lexical environment) 를 참고하기 바란다.

3. 스코프

사실 대부분 var과 let, const를 배우는 사람들은 이 점을 세 키워드의 가장 큰 차이로 둔다.

4. 정리

그러니까 윗 내용들을 정리하자면 아래와 같다

var let const 타입 변수 변수 상수 호이스팅 undefined uninitialized uninitialized 스코프 functional block block

참고사이트

1. MDN : Javascript의 자료형

2. Poiemaweb : Scope

from http://blinders.tistory.com/102 by ccl(S) rewrite - 2021-10-18 00:01:41