티스토리 뷰
지난 포스팅에서 배열(Array)가 객체(Object)로 취급된다는 것을 확인했다. 그리고 JavaScript에서는 함수(Function)도 객체다. 본격적인 이야기를 시작하기 전에, 1급객체(First-Class Citizens)에 대해 짚고 넘어가려고 한다.
JavaScript의 함수를 1급 객체라고 표현하기도 한다. 1급 객체는 CS분야에서 자주 쓰이는 용어로, 아래와 같은 특징을 갖는다.
⊙ 변수나 데이터 구조안에 담을 수 있다.
⊙ 파라미터로 전달 할 수 있다.
⊙ 반환값(return value)으로 사용할 수 있다.
⊙ 동적으로 프로퍼티 할당이 가능하다.
JavaScript의 함수는 위의 조건을 모두 만족한다. JavaScript의 함수는 입력값을 받아 결과를 반환하는 구조로, JAVA와 같은 언어의 함수와 비슷하지만 함수 자체가 '값'으로 취급(값으로 취급되어야 위와 같은 특징을 만족할 수 있다.)된다는 특징이 있다.
1. 함수정의
JavaScript의 함수 선언 방식은 크게 3가지로 나뉜다. 예제를 통해 알아보자.
// 함수 선언문 방식. function add(a,b) { return a+b; } // 함수 표현식 방식. var add = function (a,b) { return a+b; } // 함수 생성자 방식. 거의 안씀. new Function('a','b','return a+b');
먼저 예제의 첫번째인 함수 선언문 방식은 C나 JAVA에서 함수를 선언하는 것과 비슷하다고 생각하면 된다. 그리고 함수 표현식 방식은 JavaScript에서 가장 많이 사용되는 함수 정의 방식으로, 익명함수를 생성하여 변수에 할당하는 형태를 띄고있다.
한편, 함수 생성자 방식은 Function이라는 생성자를 사용하여 함수를 생성하는 방식으로, 불편하여 거의 사용하지 않는다. 문법은 아래와 같다.
new Function(arg1, arg2, ... , argN, functionBody)
진짜 불편하다.
2. 함수호출
JavaScript에서는 함수를 다양하게 호출할 수 있다. C나 JAVA와 같은 방식으로 함수를 호출할 수도 있고 다른 방식도 있다. 예제를 통해 알아보자.
// 1. 기본적인 호출 방식 var result = add(a, b); // 2. 콜백함수를 이벤트핸들러에 등록함. window.onload = function() { alert('이벤트 핸들러에 함수를 등록함.'); } // 3. 즉시실행함수 (fuction (value) { console.log('함수를 선언과 동시에 호출한다. 입력값: '+value); })('abcdef');
콜백함수의 호출은 이벤트핸들러가 담당하며, 특정 이벤트가 발생했을 때 등록된 콜백함수를 호출하는 방식이다. 이는 비동기 프로그래밍에서 자주 쓰이는 기법이며, Node.js와 각종 프론트엔드 프레임워크에서 사용된다.
즉시실행함수는 함수를 선언과 동시에 호출하는 함수를 뜻한다. 최초 한 번만 실행할 내용을 즉시실행함수에 넣어 쓰면 좋다.
3. 함수도 객체다.
함수도 객체이므로 일반적인 객체의 기능을 모두 쓸 수 있다. 그리고 추가적으로 함수의 기능(호출 됐을 때 지정된 로직을 수행함.)을 수행할 수 있다. 그런데 함수에는 일반 객체와 달리 함수만의 표준 프로퍼티가 정의되어있다. 아래 예제와 실행 결과를 보자.
function add(a,b) { return a+b; } console.dir(add);
add함수에 별다른 프로퍼티를 선언하지 않았지만 arguments, caller, length, name 등의 프로퍼티가 보인다.
arguments: 함수를 호출할 때 전달된 인자 값을 갖고 있는 유사배열객체
caller: 이 함수를 호출한 함수.
length: 함수에 정의된 파라미터의 개수.
name: 함수의 이름.
prototype 프로퍼티와 __proto__ 프로퍼티에 주목해보자. __proto__는 지난 포스팅에서 다룬적이 있다. 함수도 객체이므로 __proto__ 프로퍼티를 갖고 있다. 다만, 일반적인 객체의 __proto__는 Object.prototype을 가리켰다면 함수의 __proto__는 Function.prototype을 가리킨다.(Function.prototype의 __proto__는 Object.prototype을 가리킨다.)
위 예제의 실행 결과를 보면 Function.prototype은 constructor 프로퍼티와 apply(), call(), toString()등의 메서드를 갖고 있다.
그러면 prototype 프로퍼티는 정체가 뭘까? __proto__ 프로퍼티와 다르다는 것은 분명한 것 같다. prototype 프로퍼티는 constructor라는 프로퍼티만 갖고 있는 객체를 가리키고 있기 때문이다.
4. 생성자 함수와 프로토타입
지난 포스팅에서 객체 생성 방법에는 생성자 함수 방식이 있다고 했다. 거기서 다루었던 예제를 다시 한 번 째려보자.
var Student = function (name) { this.name = name; } var student = new Student('preamtree');
이 예제에서 Student 함수의 __proto__ 프로퍼티는 Function.prototype을 가리킬 것이다. 그리고 prototype 프로퍼티는 위에서 확인한대로 constructor라는 프로퍼티만 갖고 있는 객체를 가리킬 것이다. 그리고 이 객체는 student 변수에 할당된 객체(생성자 함수로 생성된 객체)의 부모객체가 된다.
즉, 생성자함수의 prototype 프로퍼티가 가리키는 객체는 생성자함수로 생성된 객체의 __proto__ 프로퍼티가 가리키는 객체와 같다.
이해가 어려운 독자를 위해 이를 그림으로 나타내봤다.
Student()라는 생성자 함수의 prototype 프로퍼티는 Student.prototype을 가리키고, 이는 해당 생성자를 통해 생성된 객체의 부모객체이다. 또한 부모객체의 constructor 프로퍼티는 생성자 함수를 가리키고 있다. 그리고 함수도 객체이므로 함수 자체의 __proto__ 프로퍼티가 존재하고, 이는 Function.prototype 객체를 가리킨다.
-끝-
출처 및 참고
http://insanehong.kr/post/javascript-scope/
https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/%ED%95%A8%EC%88%98
송형주, 고현준, 『인사이드 자바스크립트』, 한빛미디어(2016)
'IT > 개발팁' 카테고리의 다른 글
JavaScript와 객체지향 프로그래밍(OOP) 구현 (0) | 2018.03.15 |
---|---|
JavaScript의 this 바인딩 (0) | 2018.02.25 |
JavaScript에서는 배열(Array)도 객체(Object)다 (0) | 2018.02.15 |
JavaScript의 객체(Object) 기본 개념 (0) | 2018.02.08 |
Spring과 DB이야기 - 3. Transaction 처리 (0) | 2017.12.17 |