모던자바스크립트 "4장 변수", "13장 스코프"을 읽으며 정리하여 공부했습니다.
- 사실 어디서 많이 들어봤고 면접단골질문이라는 실행컨텍스트..를 공부하려고했는데,
- 읽다보니 var와 스코프, lexical environment에 대한 이해가 전무하다고 판단하여 변수와 스코프를 먼저 공부하게 되었다.
- 하핫
- let, const까지 공부하면 소화할 수 있으려나...
- 모던자바스크립트 딥 다이브를 읽고계시다면,
- 책에서는 다른 챕터로 다루었지만, 변수와 스코프는 이어지는 맥락으로 설명되기 때문에 변수를 읽은 후 스코프를 읽으면 더 이해하기 좋을 것 같습니다.
var의 특징과 장단점
var은 우선 ES6에서는 const,let에 밀려 사용이 권장되어 지지 않는다.
var에 어떤 특성이 단점으로 나타났기 때문인가?
특성에 대해 정리해보자.
1. 우선 var은 블록레벨 스코프를 지원하지 않는다. 함수레벨 스코프만 지원한다.
이 의미는,
for, if등 블록레벨에서 var 변수를 사용하면 의도치않은 전역변수가 되어버리는 경우가 생긴다는 소리다.
(전역변수의 문제점에 대해서는 내일 "14장 전역변수의 문제점" 에 대해 공부해보고 추가할 내용이 있으면 포스팅할 예정.)
2. 게다가 같은 스코프내에서 중복선언을 허용한다.
let,const 키워드로 선언했다면, 같은 스코프 내에서 중복선언이 이루어질 때 에러가 발생한다.
하지만 에러가 발생하지 않으면?
의도치않게 변수를 재할당하게되고 예상한 값과 다른 값이 저장되게 된다.
3. var키워드로 선언하면, 선언 후 바로 undefined로 초기화가 이루어진다.
선언하고, 우리가 원하는 값을 할당하기 전에 undefined라는 원시값으로 초기화가 이미 이루어져있다는 뜻이다.
이런 자동초기화를 통해,
이전 어플리케이션이 사용하고 남은 값이 메모리에 남아있어 쓰레기 값이 할당될 수 있는 문제를 원천 차단한다.
(let, const는 안그러나? 궁금.... 내일 "15장 let,const키워드와 블록레벨스코프" 부분 읽고 추가하겠슴!!)
4. undefined로 초기화되어 저장된 메모리 주소와 사용자가 할당한 메모리 주소가 다르다.
- 만약,
1번 라인에서 선언된 score이 소스코드 평가과정에서 undefined를 메모리 0x000000F2에 저장되었다면,
2번 라인에서 80을 할당할때는 메모리 0x00001332라는 새로운 공간을 확보하고 80이란 값을 저장한다.
var score; // 1번 score = 80; // 2번
(책에는 var만 설명이 되어있어서 이것도 let, const는 안그러는지 궁금....아마 똑같을 것 같긴함.)
여러번 값을 재할당했다면, 할 때마다 새로운 메모리 공간을 확보하게 된다.
그러면 당연히 undefined, 80이 담긴 메모리 주소는 어떤 식별자도 참조하지 않게 된다.
이런 메모리 누수(memory leak)를 해결하기 위해 자바스크립트의 가비지 콜렉터가 메모리를 해제할 것이다.
자바스크립트는 매니지드 언어라서, 언어가 자체적으로 메모리 할당 및 해제를 관리한다.
스코프, 스코프 체인과 렉시컬 환경 (Lexical environment)
스코프를 정의하자면
- 식별자의 유효한 범위, 즉 다른 코드가 자기를 참조할 수 있는 범위를 의미한다.
- 자바스크립트가 실행될 때, 필요한 식별자를 검색할 때 사용하는 규칙
이라도 할 수 있다.
식별자는 유일해야 한다. 하난의 값은 하나의 유일한 식별자에 "연결(name binding)"되어야 한다.
렉시컬 환경, Lexical environment
- 코드가 어디서 실행되고, 주변에 어떤 코드가 있는지를 의미
자바스크립트가 런타임되기 전, 소스코드 평과 과정에서 "렉시컬 환경"을 생성한다.
렉시컬 환경이라는 자료구조는 한 스코프내에 어떤 변수, 함수 등이 존재하는지를 key-value형태로 저장해 놓는다.
이렇게 만든 렉시컬 환경을 단방향으로,
즉 가장 안쪽(로컬)에서 바깥쪽(전역)으로 chaining한게 스코프 체인이다.
단방향 연결은 부모-자식간의 상속과 비슷한데, 자식이 부모를 참조할 수는 있지만 그 반대는 불가능한 점이 비슷하다.
로컬스코프에서 전역스코프를 참조할 수 있지만, 전역스코프에서 로컬스코프를 참조할 수는 없다.
자바스크립트는 동적 스코프(함수를 어디서 호출하는지에 따라 함수의 상위 스코프를 결정함)가 아닌,
렉시컬 스코프(함수를 어디서 정의했는지에 따라 함수의 상위 스코프를 결정함) 를 따른다.
즉 ,함수의 상위 스코프는 언제나 자신이 정의된 스코프이다.
한 번 함수가 정의되면 정적으로 결정된다.
런타임 전, 함수 정의가 실행되어 생성된 함수 객체는 이렇게 결정된 "상위 스코프"를 기억하여, 함수를 호출할 때 참조할 수 있게 한다.
'Web Development' 카테고리의 다른 글
[JS] Event loop 문제 도전하기 + 풀이 (0) | 2022.01.17 |
---|---|
callback 함수를 왜 쓰나? (0) | 2022.01.07 |
자바스크립트의 특징; 인터프리터, 명령형, 함수형, 프로토타입 기반 객체지향 언어 ? (0) | 2022.01.03 |
align-content vs align-items 차이 (0) | 2021.08.23 |
[JS] 생성자 함수 장점, 객체 리터럴 단점, 유용한 Object methods (0) | 2021.08.14 |