코드 블록
: { ... }
: 이 안에서 선언한 변수는 블록 안에서만 사용할 수 있음
중첩 함수
: 함수 내부에서 선언한 함수
function sayHiBye(firstName, lastName) {
// 헬퍼(helper) 중첩 함수
function getFullName() {
return firstName + " " + lastName;
}
alert( "Hello, " + getFullName() );
alert( "Bye, " + getFullName() );
}
렉시컬 환경 (Lexical Environment)
: 자바스크립트에서 실행중인 함수, 코드블록, 스크립트 전체가 가지는
내부 숨김 연관 객체 (internal hidden associated object)
: 변수는 특수 내부 객체인 환경 레코드의 프로퍼티임
: 명세서에서 자바스크립트가 어떻게 동작하는데 쓰이는 이론상의 객체
: 코드로 조작 불가
- 환경 레코드 (Environment Record)
: 모든 지역 변수를 프로퍼티로 저장하고 있는 객체
: this 값과 같은 기타 정보가 저장됨
- 외부 렉시컬 환경에 대한 참조
: 외부 코드와 연관됨
- 전역 렉시컬 환경
: 스크립트 전체와 관련된 렉시컬 환경
전역 렉시컬 환경의 변화
1. 스크립트가 시작되면 스크립트 내에서 선언한 변수 전체가 렉시컬 환경에 올라감
: 이 때 변수의 상태는 특수 내부 상태인 uninitialized가 됨
: 자바스크립트 엔진이 'let 변수명' 코드를 만나기 전까지 이 변수를 참조할 수 없음
2. 'let 변수명' 코드를 컴파일하면 해당 변수의 값은 undefined가 됨
3. 해당 변수에 값이 할당 될 때 값이 생김
함수 선언문
: 함수는 일반 변수와 달리 바로 초기화 됨
: 함수 선언 문으로 선언한 함수는 렉시컬 환경이 만들어지는 즉시 사용 가능
: 선언되기 전에도 함수를 사용할 수 있는 이유
: 변수에 함수를 하당한 함수 표현식은 해당하지 않음
내부와 외부 렉시컬 환경
: 함수가 호출 중인 동안에는 함수를 위한 내부 렉시컬 환경과 내부 렉시컬 환경이 가리키는 외부 렉시컬 환경을 가짐
: 내부 렉시컬 환경은 외부 렉시컬 환경에 대한 참조를 가짐
: 코드에서 변수에 접근할 때는 먼저 내부 렉시컬 환경을 검색 범위로 잡음
: 내부 렉시컬 환경에서 원하는 변수를 찾지 못하면 검색 범위를 내부 렉시컬 환경이 참조하는 외부 렉시컬 환경으로 확장
: 이 과정은 검색 범위가 점역 렉시컬 환경으로 확장될 때까지 반복
: 전역 렉시컬 환경에 도달할 때 까지 변수를 찾지 못하면 엄격 모드에서는 에러 발생
: 하위 호환성을 위해 비 엄격 모드에서는 정의 되지 않은 변수에 값을 할당 하려고 할 시 새로운 전역 변수가 만들어짐
함수를 반환하는 함수
function makeCounter() {
let count = 0;
return function() {
return count++;
};
}
let counter = makeCounter();
: 위 예시에서 makeCounter()를 호출하면 호출할 때마다 새로운 렉시컬 객체가 만들어지고
여기에 makeCounter를 실행하는데 필요한 변수들이 저장됨
: 모든 함수는 함수가 생성된 곳의 렉시컬 환경에 대한 참조를 [[Environment]]라는 숨김 프로퍼티에 저장
: counter()를 여러번 호출하면 count 변수가 증가하는 이유임
※ 클로저 (closure)
: 외부 변수를 기억하고 이 외부 변수에 접근할 수 있는 함수
: 자바스크립트에서는 모든 함수가 클로저가 됨
가비지 컬렉션
: 호출이 끝난 후에 가비지 컬렉션에 의해 삭제되지 않는 중첩함수는
중첩함수의 [[Environment]] 프로퍼티에 외부 함수 렉시컬 환경에 대한 정보가 저장되어
도달 가능한 상태이기 때문
function f() {
let value = 123;
return function() {
alert(value);
}
}
let g = f(); // g.[[Environment]]에 f() 호출 시 만들어지는
// 렉시컬 환경 정보가 저장됩니다.
function f() {
let value = 123;
return function() {
alert(value);
}
}
let g = f(); // g가 살아있는 동안엔 연관 렉시컬 환경도 메모리에 살아있습니다.
g = null; // 도달할 수 없는 상태가 되었으므로 메모리에서 삭제됩니다.
최적화 프로세스
: 이론상으로는 함수가 살아있는 동안에는 모든 외부 변수가 메모리에 유지 되지만
실제 자바스크립트 엔진이 이를 지속해서 최적화를 수행
: 자바스크립트 엔진은 변수 사용을 분석하고 외부 변수가 사용되지 않는다고 판단되면
이를 메모리에서 제거함
var
: 자바스크립트 초기에 사용하던 변수형
: const나 let과 달리 블록 스코프가 없어 함수 스코프 혹은 전역 스코프로 작동하기 때문에
블록 밖에서도 접근이 가능
: var 선언은 함수가 시작 될 때 처리되며 선언 위치와 상관없이 함수 본문이 시작되는
지점에서 정의됨
즉시 실행 함수식
: 선언과 동시에 실행되는 함수
// IIFE를 만드는 방법
(function() {
alert("함수를 괄호로 둘러싸기");
})();
(function() {
alert("전체를 괄호로 둘러싸기");
}());
!function() {
alert("표현식 앞에 비트 NOT 연산자 붙이기");
}();
+function() {
alert("표현식 앞에 단항 덧셈 연산자 붙이기");
}();
Refference
변수의 유효범위와 클로저
ko.javascript.info
오래된 'var'
ko.javascript.info
'Programming > JavaScript' 카테고리의 다른 글
모던 자바스크립트 (함수) 4-4. setTiemout과 setInterval을 이용한 호출 스케줄링 (0) | 2022.04.23 |
---|---|
모던 자바스크립트 (함수) 4-3. 전역 객체 / 함수 표현식 / new Function 문법 (0) | 2022.04.23 |
모던 자바스크립트 (함수) 4-1. 재귀와 스택 / 나머지 매개변수와 스프레드 문법 (0) | 2022.04.19 |
javascript의 데이터를 멋있게 다루는 방법에 대한 총 정리. (filter / find / reduce / map / forEach /new Map / new Set / lodash / regex) (0) | 2022.04.19 |
자바스크립트 배열의 요소 삭제하기 (0) | 2022.04.19 |