본문 바로가기

WEB/JavaScript

JS의 데이터 타입 4 (함수)

함수의 정의

함수를 정의하는 방식에는 3가지가 있다. 각각의 방식으로 생성된 함수들은 조금씩 다르게 작동한다.

  1. 함수 선언문(statement) 사용
  2. 함수 표현식(expression) 사용
  3. Function() 생성자 사용

함수 리터럴

전에도 말했듯이 자바스크립트에서 함수는 일반 객체처럼 값으로 취급된다. 함수 선언문과 함수 표현식 모두 이 함수 리터럴을 사용해서 함수를 생성한다.

function add(a, b) {
    return a + b;
}

함수 리터럴은 function 키워드, 함수 이름, 매개 변수, 함수 본문으로 이루어져 있다. 함수 리터럴을 사용할 때 함수 이름을 쓰는 것은 선택 사항이다. 만약 함수 이름을 쓰지 않는다면 그 함수는 익명함수가 된다.

함수 선언문

함수 선언문 형식은 함수 리터럴의 형태와 같다. 중요한 점은 함수 선언문 형식으로 함수를 생성할 때 함수 이름을 써야한다는 것이다.

함수 표현식

앞에서 말했듯이 자바스크립트에서 함수는 값으로 취급된다. 따라서 변수에 함수를 할당하는 게 가능하다. 이렇게 변수에 함수 리터럴을 통해서 함수를 할당하는 것을 함수 표현식이라고 한다. 함수 표현식에 할당하는 함수 리터럴에는 함수 이름을 할당할 필요가 없다.

함수 표현식에서 함수를 할당한 변수는 변수일 뿐 함수의 이름이 아니라는 것을 잘 알아둬야 한다.

위에서 볼 수 있듯이 함수 표현식으로 함수를 생성할 때에는 변수에 익명 함수를 할당한다. 이를 익명 함수 표현식이라고 부른다. 이렇게 익명 함수의 호출은 할당된 변수의 이름에 함수 호출 연산자인 ()를 붙여서 실행한다.

반대로 함수 이름이 있는 함수를 변수에 할당한 함수 표현식을 기명 함수 표현식이라고 한다. 기명 함수 표현식을 사용할 때에는 주의할 점이 몇 가지 있다.

기명 함수 표현식에서 사용된 함수 이름은 함수 외부에서 접근할 수 없다. 따라서 기명 함수 표현식에 사용된 함수 이름은 해당 함수 내부에서 재귀적으로 호출하거나 다른 용도로 사용된다.

function() 생성자

앞에서 본 함수 선언문과 함수 표현식으로 생성된 함수들도 내부적으로 function() 생성자를 통해서 생성된다고 볼 수 있다.

new Function (arg1, arg2, ... argN, functionBody)
  • arg1, arg2, ... argN : 함수의 매개변수 (0개 이상)
  • functionBody : 함수의 본문이 될 문자열

일반적인 경우에는 함수를 생성하기 위해서 function() 생성자를 사용하지는 않는다.

함수 호이스팅

위에서 함수를 생성하는 3가지 방법을 알아봤다. 이 방식들 사이의 동작 방식은 조금씩 다르다. 그중의 하나가 함수 호이스팅이다. 함수 선언문을 사용하면 이 함수 호이스팅이 발생하게 된다. 예시를 통해서 자세히 알아보자.

함수 호이스팅이란 함수가 선언되기 이전에 함수를 사용할 수 있는 현상이라고 할 수 있다. 이런 함수 호이스팅 현상 때문에 함수를 선언할 때에는 함수 표현식을 권장한다고 한다. 함수 표현식을 사용하게 된다면 위와 다른 결과가 나오게 된다.

함수 객체

자바스크립트에서 함수는 객체다. 즉, 함수가 함수의 기능뿐만 아니라 객체의 기능도 할 수 있다는 말이다.

위 코드를 보면 알 수 있듯이 자바스크립트에서 함수는 프로퍼티를 가질 수 있다.

위에서 말했던 것 처럼 자바스크립트에서 함수는 객체다. 이 말은 함수도 일반 객체처럼 취급될 수 있다는 것이다. 이렇게 일반적으로 다른 객체들에 적용할 수 있는 연산을 지원하는 것을 일급 객체라고 한다.

일급 객체의 조건에는

  • 변수나 데이터 구조(배열, 객체)안에 담을 수 있다.
  • 함수의 인자로 전달 할 수 있다.
  • 반환값으로 사용할 수 있다.
  • 할당에 사용된 이름과 관계없이 고유한 구별이 가능하다.
  • 동적으로 프로퍼티 할당이 가능하다.

출처: 위키피디아

가 있다. 자바스크립트의 함수는 위의 조건을 모두 만족하므로 일급 객체라고 할 수 있다. 함수가 일급 객체라는 말은 일반적인 객체들처럼 하나의 으로써 사용될 수 있다는 말이다.

함수 객체의 기본 프로퍼티

계속 말해왔듯이 자바스크립트에서 함수는 객체의 일종이다. 함수는 일반적인 객체의 기능과 미리 정의된 함수 코드를 실행하는 기능을 가지고 있다. 함수는 일반적인 객체와 다르게 함수만의 추가적인 표준 프로퍼티가 정의되어 있다.

function add(a, b) {
    return a + b;
}

console.dir(add);

위 코드를 실행하게 된다면 객체에서 본 적 없던 새로운 프로퍼티들을 볼 수 있다. arguments, caller, length 같은 프로퍼티들은 함수가 생성될 때 포함되는 표준 프로퍼티들이다.



함수의 name 프로퍼티는 함수의 이름을 나타낸다. 만약 이름이 없는 익명 함수라면 name 프로퍼티는 빈 문자열이 된다.

caller 프로퍼티는 자신을 호출한 함수를 나타낸다. 호출되지 않았다면 null 값이 된다. arguments 프로퍼티는 함수가 호출될 때 전달된 인자값을 나타낸다. caller 프로퍼티와 같게 호출되지 않았다면 null 값이 된다. arguments 프로퍼티와 비슷하게 length 프로퍼티는 함수를 정의할 때 정의된 인자의 개수를 나타낸다.

그리고 모든 자바스크립트 객체가 가지고 있는 프로퍼티인 [[Prototype]] (__proto__) 프로퍼티는 당연히 함수도 가지고 있다. 이 프로퍼티를 통해서 자식의 부모 역할을 하는 프로토타입 객체를 가리킨다. 함수의 프로토타입 객체는 Function.prototype 객체다. 이 Function.prototype 객체의 프로퍼티를 보면 위에서 본 표준 프로퍼티들이 있다.

prototype 프로퍼티

자바스크립트의 모든 함수들은 객체로서 prototype 프로퍼티를 가지고 있다. 이 prototype 프로퍼티는 prototype 프로퍼티는 앞에서 말한 자신의 부모를 가리키는 [[Prototype]] 프로퍼티와는 다른 프로퍼티이다.

[[Prototype]] 프로퍼티는 자신의 부모 역할을 하는 프로토타입 객체를 가리키는 프로퍼티이다. 하지만 이와 다르게 prototype 프로퍼티는 자신이 생성자로 쓰일 때, 자식 객체들이 생성될 때 원형으로 참조할 프로토타입 객체를 가리킨다. 다시 말해, [[Prototype]] 프로퍼티는 자신의 원형이 되는(부모 객체의) 프로토타입 객체를 가리키고, prototype 프로퍼티는 자신을 통해서 만들어질 객체들이(자식 객체들이) 참조할 프로토타입 객체를 가리킨다.

prototype 프로퍼티는 함수가 생성될 때 만들어진다. 즉 prototype 프로퍼티는 함수 객체만 가지고 있다는 말이다. 이 prototype 프로퍼티는 constructor 프로퍼티 하나만 있는 객체를 가리킨다. (물론 객체이기 때문에 [[Prototype]] 프로퍼티를 가지고 있다.) 이 constructor 프로퍼티는 해당 객체의 생성자(prototype 프로퍼티가 가리키는 객체)



이렇게 함수 객체와 프로토타입 객체는 prototype 프로퍼티와 constructor 프로퍼티를 통해서 서로를 연결해준다.

'WEB > JavaScript' 카테고리의 다른 글

프로토타입 체이닝(1)  (0) 2018.05.20
JS의 데이터 타입 5 (함수)  (0) 2018.05.17
JS의 데이터 타입 3 (프로토타입)  (0) 2018.05.02
JS의 데이터 타입 2 (객체)  (0) 2018.05.01
JS의 데이터 타입 1 (기본 타입)  (0) 2018.04.22