※ 익명함수, 유명함수, 즉시실행함수 / 클로저
1. 일급함수
- 함수를 다른 변수와 동일하게 다루는 언어는 일급 함수를 가졌다고 표현한다. 일급 함수를 가진 언어에서는 함수를 다른 함수에 인수로 제공하거나, 함수가 함수를 반환할 수 있으며, 변수에도 할당할 수 있다.(함수가 다른 일급 객체와 동일하게 다루어 질때, 일급 함수라고 지칭한다.)
const foo = function() {
console.log("foobar");
}
// 변수를 사용해 호출
foo();
함수를 인자로 전달하는 예시
function sayHello() {
return "Hello, ";
}
function greeting(helloMessage, name) {
console.log(helloMessage() + name);
}
// `sayHello`를 `greeting` 함수에 인자로 전달
greeting(sayHello, "JavaScript!");
※ 일급객체의 속성:
- 변수에 할당(assignment)할 수 있다.
- 다른 함수를 인자(argument)로 전달 받는다.
- 다른 함수의 결과로서 리턴될 수 있다.
1) 익명함수
- 함수명 대신 변수명에 함수 코드를 저장하는 구현 방식. 익명 함수의 소스 코드는 변수값이므로 끝에 세미콜론 ; 을 대입한다. 익명 함수는 호출 시 변수명을 함수명처럼 사용하면 된다.
var 변수명 = function( 매개변수 )
{
실행문;
};
2) 유명함수
- 이름이 있는 함수.
const func = function a() {
console.log(a);
};
func.name;
// a
3) 즉시실행함수
- (IIFE, Immediately Invoked Function Expression)는 정의되자마자 즉시 실행되는 함수를 말한다.
(function () {
console.log("abcd");
})();
// 화살표 함수로도 사용 가능하다.
(() => {
console.log("abcd");
})();
⌘ 사용하는 이유?
1. 필요없는 전역 변수의 생성을 줄일 수 있다.
- 함수를 생성하면 그 함수는 전역 변수로써 남아있게 되고, 많은 변수의 생성은 전역 스코프를 오염시킬 수 있다.
- 즉시실행함수를 선언하면 내부 변수가 전역으로 저장되지 않기 때문에 전역 스코프의 오염을 줄일 수 있다.
2. private한 변수를 만들 수 있다.
- 즉시실행함수는 외부에서 접근 할 수 없는 자체적인 스코프를 가지게된다. 이는 클로저의 사용 목적과도 비슷하며 내부 변수를 외부로부터 private하게 보호 할 수 있다는 장점이 있다.
⌘ 언제 사용하나?
- 단 한 번의 사용이 필요한 함수. 예를 들어, 변수를 초기화하는 함수에 사용한다.
let isAdult;
(function init(age) {
let currentAge = age;
if (age >= 20) {
isAdult = true;
} else {
isAdult = false;
}
})(20);
console.log(isAdult); // true
console.log(currentAge); // Uncaught ReferenceError: currentAge is not defined
- 자바스크립트 모듈을 만들 때도 활용한다.
const Counter = (function counterIIFE() {
// 현재 counter 값을 저장하기 위한 변수
let current = 0;
return {
// 즉시실행함수로써 반환되는 객체
};
})();
2. 클로저 함수
- 클로저는 함수와 그 함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합.
function outerFunc() {
var x = 10;
var innerFunc = function () { console.log(x); };
innerFunc();
}
outerFunc(); // 10
함수 innerFunc가 함수 outerFunc의 내부에 선언된 내부함수이므로 함수 innerFunc는 자신이 속한 렉시컬 스코프(전역, 함수 outerFunc, 자신의 스코프)를 참조할 수 있다. 이것을 실행 컨텍스트(실행 가능한 코드가 실행되기 위해 필요한 환경)의 관점에서 설명해보자.
내부함수 innerFunc가 호출되면 자신의 실행 컨텍스트가 실행 컨텍스트 스택에 쌓이고 변수 객체(Variable Object)와 스코프 체인(Scope chain) 그리고 this에 바인딩할 객체가 결정된다. 이때 스코프 체인은 전역 스코프를 가리키는 전역 객체와 함수 outerFunc의 스코프를 가리키는 함수 outerFunc의 활성 객체(Activation object) 그리고 함수 자신의 스코프를 가리키는 활성 객체를 순차적으로 바인딩한다. 스코프 체인이 바인딩한 객체가 바로 렉시컬 스코프의 실체이다.
내부함수 innerFunc가 자신을 포함하고 있는 외부함수 outerFunc의 변수 x에 접근할 수 있는 것, 다시 말해 상위 스코프에 접근할 수 있는 것은 렉시컬 스코프의 레퍼런스를 차례대로 저장하고 있는 실행 컨텍스트의 스코프 체인을 자바스크립트 엔진이 검색하였기에 가능한 것이다. 좀더 자세히 설명하면 아래와 같다.
- innerFunc 함수 스코프(함수 자신의 스코프를 가리키는 활성 객체) 내에서 변수 x를 검색한다. 검색이 실패하였다.
- innerFunc 함수를 포함하는 외부 함수 outerFunc의 스코프(함수 outerFunc의 스코프를 가리키는 함수 outerFunc의 활성 객체)에서 변수 x를 검색한다. 검색이 성공하였다.
※ 스코프 체인(Scope Chain): 일종의 리스트로서 전역 객체와 중첩된 함수의 스코프의 레퍼런스를 차례로 저장하고, 의미 그대로 각각의 스코프가 어떻게 연결(chain)되고 있는지 보여주는 것
⌘ 내부함수 innerFunc를 반환하도록 변경해 보자.
function outerFunc() {
var x = 10;
var innerFunc = function () { console.log(x); };
return innerFunc;
}
/**
* 함수 outerFunc를 호출하면 내부 함수 innerFunc가 반환된다.
* 그리고 함수 outerFunc의 실행 컨텍스트는 소멸한다.
*/
var inner = outerFunc();
inner(); // 10
자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되더라도 외부함수의 지역 변수에 접근할 수 있는데 이러한 함수를 클로저(Closure)라고 부른다.
{클로저는 반환된 내부함수가 자신이 선언됐을 때의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 환경(스코프) 밖에서 호출되어도 그 환경(스코프)에 접근할 수 있는 함수.}
⌘ 언제 활용하나?
- 상태유지, 전역변수 사용의 억제, 정보 은닉 등등
⌘ 참조
- MDN,
- 클로저: https://poiemaweb.com/js-closure
- 즉시실행함수: https://jongminfire.dev/java-script-%EC%A6%89%EC%8B%9C%EC%8B%A4%ED%96%89%ED%95%A8%EC%88%98-i
- 유명함수: https://dc7303.github.io/javascript/2019/11/25/jsNamedFunction/
- 익명함수: https://velog.io/@blackb0x/%EC%9D%B5%EB%AA%85%ED%95%A8%EC%88%98Anonymous-function
'코딩 > Javascript' 카테고리의 다른 글
[스터디 4일차] 22.12.21 - ES6 클래스 이해하기 (0) | 2022.12.19 |
---|---|
[스터디] 3일차(2022.12.17) - 얕은 복사, 깊은 복사 (0) | 2022.12.19 |
[스터디] 22.12.03 - 자료구조 알아보기(Array, Set, Object) (0) | 2022.12.02 |
TIL(22.09.28) - Vue js 웹뷰 프로젝트 내 이벤트 함수, 컴퓨터에서는 동작하는데 모바일에서는 동작 안하는 경우 (0) | 2022.09.28 |
22.09.17 WIL - Api 연동 시 default값 설정 & 체크박스 설정 (0) | 2022.09.17 |