들어가며
함수에 대한 내용입니다.
책 인사이드 자바스크립트(4.1~4.3)를 참고하였습니다.
함수의 정의
함수를 정의하는 방식에는 크게 세 가지 방식이 있다.
- 함수 선언문
- 함수 표현식
- Function() 생성자 함수
그리고 1번과 2번은 함수 리터럴 방식 을 이용해서 선언된다. 3번은 말 그대로, Function() 생성자 함수 를 통해서 선언된다.
함수 리터럴 방식
리터럴이란, 선언함과 동시에 값 또는 코드를 지정해주는 것을 말한다.
-참고1
함수 선언문 - 기명 함수
function fInit(a) {
console.log(a);
}
함수를 선언할 때 이름이 꼭 있어야(기명) 한다.
그리고 선언문 이기 때문에 호이스팅이 일어날 수 있다. 때문에 코드 구성을 엉성하게 만들 수 있어서, 되도록이면 선언문으로 함수를 만들지 않는 것이 좋다.
함수 표현식 - 기명/익명 함수
/* 1: 익명 */
var fExp = function(a) {
console.log(a);
}
/* 2: 기명 */
var fExp = function inner(a) {
console.log(a);
}
함수 선언 시 이름은 있어도(기명) 되고, 없어도(익명) 된다.
그리고 함수를 만들 때, 변수에 할당해서 만들기 때문에 호이스팅이 일어나지 않는다.
호이스팅이 일어나지 않는 이유를 컴파일 과정 중 일부를 예시로 들어 설명해보겠다.
- 컴파일 과정에서 (
== Execution Context를 만들 때, Creation phase 에서
) Variable Environment component(@1)를 만든다. - 이 때 Record Environment(@2)를 만들 때, 선언된 변수와 함수를 scope 목록 내에 추가해준다.
- 이후 일련의 다른 과정을 거치며 Execution Context가 만들어진다.
위에서 선언된 변수와 함수 라고 했다. 함수 표현식은, 선언이 아니라 할당이 이루어지는 것 (var fExp = ...
) 이기 때문에 컴파일 과정 중에 scope 목록에 들어가지 못하게 된다.
즉 함수 표현식으로 함수가 만들어지기 전에, 함수의 사용이 일어난다면 scope 내에서 함수를 탐색 할 수가 없기 때문에 (RHS 탐색 실패) ReferenceError 가 발생하게 된다.
함수를 표현식으로 만들 때, 기명으로 만드는 경우에는 함수 내부의 context에는 기명 함수에 대한 접근이 가능하기 때문에 2번 코드를 아래처럼 바꾼다면, 실행은 가능하다. (물론 RangeError가 발생한다)
var fExp = function inner(a) {
inner(a);
}
@1. fExp
가 var
로 선언 되었기 때문이다. 만약 const
나 let
으로 선언되었다면 Lexical Environment component 를 만들게 된다.
@2. scope 목록 내에 선언만 하는 것으로, 함수의 이름과 식별자를 바인딩 해준다. (값의 할당을 말하는 것이 아님)
Function()
생성자 함수로 함수 만들기
var add = new Function('x', 'y', 'return x+y');
console.log(add(3, 4)); // 7
생성자 함수로 만들어진 함수 또한 함수를 변수에 할당 함으로써 만들기 때문에 마찬가지로 호이스팅이 일어나지 않는다.
정리
함수는 크게 함수 리터럴 방식으로 만들거나, Function() 생성자 함수로 만들 수 있다.
함수 리터럴 방식으로 만드는 방법에는 함수 선언문과 함수 표현식이 있다. 함수 선언문의 경우 호이스팅이 일어날 수 있기 때문에, 책에서는 호이스팅이 일어나지 않는 함수 표현식으로 함수를 만드는 방식을 추천하였다.
함수를 리터럴 방식으로 만들던, 생성자를 통해서 만들던 내부적으로는 Function() 생성자 함수로 함수가 생성 된다.
함수도 객체다
객체란 무엇일까?
당연하게도 객체 지향적 프로그래밍을 위해서는 객체를 알아둘 필요가 있다. 우스개로 객체 지향 프로그래밍을 배울 때, 붕어빵과 붕어빵 틀에 대해서 많이들 듣는다고 한다. 과연 이 예시가 객체 지향을 이해하는데 좋은 예시가 될 수 있을까? 나는 아니라고 생각한다. 객체 지향적 프로그래밍에서는 객체간의 유기적인 관계가 중요한데, 붕어빵은 우리가 먹으면 없어지는 단 하나의 객체일 뿐이다.
객체는 말하자면
어떠한 물체나 개념을 추상적으로 표현한 것
이다. 어려워 보이는 표현이다. 그렇지만 어떻게보면 가장 우리에게 친숙한 방법이 바로추상화
다. 가령걷는다
라는행위
에 대해서 생각해보자. 이 행위는 인간 뿐 아니라 코끼리, 기린 등 다른 동물에게도 적용될 수 있다. 즉 우리는 코끼리가 걸을 때나, 사람이 걸을 때나 혹은 어던 동물이 걸을 때나, 이 모든 상황에서걷는다
라는 단어로 대상의 행위를 표현한다. 이런 예시에서 우리는걷는다
라는 행위가 모든다리 달린 동물
에 대해서 추상화 되어있다고 표현할 수 있다. 이것을 코드로는,
person.walk();
giraffe.walk();
elephant.walk();
위와 같이 표현할 수 있다.
그렇다면
walk()
라는 함수로 표현되는 행위는 객체가 될 수 있을까? 그렇다. 그럼person
,giraffe
,elephant
라는 물체도 객체가 될 수 있을까? 물론 그렇다. 그런데 생각해보면 행위야 추상적인 개념이 될 수 있다쳐도 물체는 실제로 존재하는 것인데 어떻게 추상화할 수 있는지 의문이 들 수 있다. 사실 이물체
혹은인스턴스
야 말로 진정한 추상화의 집합이라고 할 수 있다.
인스턴스란 무엇일까?
나는 방금 인스턴스라는 단어를 썼다. 그렇다면 인스턴스란 무엇이고, 그 인스턴스는 어떻게 생성되는걸까?
홍길동
이라는 사람이 있다고 가정해보자. 홍길동은 어떠한 정보를 지닐 수 있는가?이름
,나이
,생일
,키
,몸무게
등을 지닐 수 있을 것이며, 문화, 지역마다 고유한 특성 또한 지닐 수 있을 것이다.
예를들어 홍길동이한국인
이라면주민등록번호
를 가질 수 있다. 생각해보면 나이, 생일, 주민등록번호라는 개념은 세상이 만들어질 때 함께 존재하던 개념이 아니다. 이는 사람이 삶을 더 편리하게 살아갈 수 있도록 만든 추상적인 개념이다.
즉, 홍길동은 사람이 가질 수 있는 추상적인 개념으로 이루어진 정보를 지니고 태어난 것이다.그렇다고해서 추상적 개념에 대한 값이 오직 수치로 표현될 수 있는 값만을 가르키는 것은 아니다. '객체란 무엇인가?'에서 설명하였듯, 어떠한 행동 또한 추상적 개념이 될 수 있다.
만약 홍길동이걷는다
,잔다
등의 행위를 할 수 있다면, 그 행동 또한 추상적 개념이 될 수 있기에, 우리는 홍길동이라는 인스턴스가 단순한 수치적 값인 속성(=Attribute) 뿐만 아니라 비수치적인 값인 명령(=Function) 또한 지닐 수 있다는 걸 알 수 있다.따라서, 홍길동은
추상적 개념(나이, 몸무게 등)에 대한 값(18살, 55kg)이나 정의된 명령(잔다, 걷는다 등)을 지닐 수 있는 어떠한 물체
, 즉, 인스턴스(=Instance)라 할 수 있다.
함수도 객체다
따라서 코드(명령)와 프로퍼티 를 가질 수 있다
함수는 일급 객체이다
함수는 일반 객체처럼 값으로 취급될 수 있다.
- 리터럴에 의해 생성
- 변수나 배열의 요소, 객체의 프로퍼티 등에 할당 가능
- 함수의 인자로 전달 가능
- 함수의 리턴값으로 전달 가능
- 동적으로 프로퍼티를 생성 및 할당 가능
Prototype
자바스크립트에서 함수는 객체이므로 prototype
을 갖는다. 이에 대해서는 지난 스터디 자료에 자세하게 설명을 적어놓았다.
함수의 다양한 형태
콜백 함수 (callback function)
콜백, 말 그대로 나중에 실행 할 함수를 말한다.
따라서 개발자
는 단지 함수를 등록만 하고, 시스템
이 어떤 이벤트가 발생했거나 혹은 특정 시점에 도달했을 때 실행시킨다.
window.onload = function() {
alert('This is the callback function');
};
setTimeout(() => {
console.log("hello")
},1000);
즉시 실행 함수 (immediate function)
말 그대로 함수를 정의하면서 바로 실행하는 함수를 말한다.
함수 전체를 ()
로 감싸주고, 그 뒤에 인자를 (arg1, arg2, ...)
형태로 넘겨주는 식으로 작성한다.
(function (name) {
console.log('This is the immediate function: '+name);
})('foo');
따라서 주로 최초 한 번의 실행만을 필요로 하는 내용 이 있을 때, 즉시 실행 함수 안에 작성한다.
내부 함수 (inner function)
함수 내부에서 함수를 선언하는 것을 말한다.
이를 통해서 (부모 함수 밖에서도 내부 함수를 호출하는) 클로저 를 만들거나, 외부에서 접근하지 못하는 헬퍼 함수 를 구현할 수 있다.
function outer() {
var a = 100;
var b = 200;
function inner() {
console.log(a+b);
}
return inner();
}
outer(); // inner() 이다
'자바스크립트 JavaScript' 카테고리의 다른 글
생성자와 This (0) | 2023.01.20 |
---|---|
This 의 바인딩 (0) | 2023.01.20 |
Closure (0) | 2023.01.18 |
Scope (0) | 2023.01.18 |
실행 컨텍스트 (Execution Context) (2) | 2023.01.17 |