4. 호이스팅
- 호이스팅 이란?
Hoist v. 들어올리다, 끌어올리다
Javascript 에서 호이스팅이라는 개념은 유효범위(scope) 최상단으로 함수선언, 변수정의를 끌어올리는걸 의미
위 코드는 정상적으로 실행이 가능하다. 이러한 이유가 호이스팅 때문이다.
var 키워드로 정의된 변수는 단순 블록{} 이 아닌 function() {} 안에서 유효합니다.
위 코드에서는 에러가 발생합니다. 이유가 뭘까요? 변수정의만 끌어올리기 때문에 undefined 상태이기 때문입니다.
이처럼 함수 표현식은 호이스팅이 일어나지 않습니다.
console.log(a);
b();
var a = 10;
function b() {
console.log('b function');
}
c(); // error
var c = function() {
console.log('c function');
};
5. 호이스팅
- 아래와 같은 경우는 어떻게 동작을 할까요?
호이스팅이 일어나면서, a 와 b 가 함수로 출력이 되는게 확인이 가능합니다.
코드의 가독성과 유지보수를 위해서는 위와 같은 코드는 가급적 지양해야 합니다.(함수와 변수 선언은 코드 상단부에
정의)
console.log(a); // function a
console.log(b); // function b
var a = 1;
var b;
function a() {
console.log("aa");
}
function b() {
console.log("bb");
}
console.log(a); // 1
6. 호이스팅
- ES6 에 추가된 let / const 는 어떨까요?
레퍼런스 에러(참조에러)가 발생 var 는 undefined 라도 반환을 하였으나, let / const 는 레퍼런스 에러가 발생을
합니다.
이거만 보고는 let / const 는 호이스팅을 하지 않는다라고 생각을 할 수도 있습니다. 하지만 결론은 그렇지 않습니다.
위 코드에서 만약 호이스팅이 발생하지 않는다면, x 값은 outer scope 를 바라봐야 할겁니다. 그런데 레퍼런스 에러가
발생을 했다는거는 호이스팅이 발생을 했다는겁니다. 그런데 왜 에러가 발생할까요?
let / const 는 실행단계에서 실행되기 전까지 접근을 할 수 없으며, 이러한 현상을 TDZ(Temporal Dead Zone) 라고
합니다. TDZ 는 선언 전에 let / const / class, default parameter 를 사용하는 것을 허용하지 않습니다.
TDZ 에는 초기화 되지 않은 변수들이 존재합니다.(메모리 공간에 할당이 되지 않은 변수들)
console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 10;
const b = 200;
const x = 'outer scope’;
(function() {
console.log(x); // Uncaught ReferenceError: Cannot access 'x' before initialization
const x = 'inner scope';
}());
8. 클로저
- 클로저란?
“A closure is the combination of a function and the lexical environment within which that function was declared.”
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.
Javascript 에서는 유효범위(scope) 는 정의가 된 순간에 정해진다. -> 이것을 lexical scope 라고 부른다.(정적
유효범위)
lexical scope 는 내 외부 스코프로 참조가 가능하나, 내부에 있는 스코프로는 참조가 불가능하다.
main() 함수 내부에 선언된 name 변수는 함수 외부에서 참조가 불가능하다.
function main(){
let name = 'zero';
}
9. 클로저
- 클로저란?
“A closure is the combination of a function and the lexical environment within which that function was declared.”
클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.
fun 변수에 sayCall() 에서 반환해주는 값을 할당해준다.(반환값은 함수)
sayCall() 은 실행 후, 실행 컨텍스트 call stack 에서 사라진다.
반환받은 값이 함수이기 때문에, 실행을 해본다. 그런데 test 라는 문자열이 출력이 된다. 메모리상에서 사라진거
아닌가?
이런거처럼 렉시컬 환경을 기억하는걸 클로저라고 부른다. 자신의 렉시컬 환경을 기억해 두었다가, 호출을하면 그
환경에 접근을 한다. 클로저에 의해 참조되는 변수를 자유변수(free variable)라고 한다.
function sayCall() {
let a = 'test';
function innerFunction() {
console.log(a);
}
return innerFunction;
}
const fun = sayCall();
fun();
10. 클로저
- 클로저의 활용
상태유지 : 현재 상태를 기억하고 변경된 최신 상태를 유지 가능
캡슐화 : 객체지향의 public / private 을 흉내낼 수 있다
* 클로저를 너무 남발하면 메모리 누수가 발생할 수 있음
12. IIFE
- IIFE 이란?
IIFE 란 정의와 동시에 실행되는 함수를 의미(즉시실행함수)
IIFE : Immediately Invoked Function Expression
즉시실행함수의 기본형태는 아래와 같습니다. 쌍괄호 사용 ()()
즉시실행함수의 주요 사용 용도는 private scope 를 만들기 위함입니다. (closure 를 활용)
이를 통해서 변수 충돌이라던가 global scope 오염을 막을 수 있습니다.
(function () {
// statements }
)();
let a = 999;
const module = (function() {
let a = 100;
const getA = () => {
return a;
};
return {
getA,
}
})();
console.log(module.getA());