인사이드 자바스크립트를 공부하며 정리하는 포스팅입니다.



1.함수 생성


자바스크립트에서 함수를 생성하는 방법은 3가지가 있습니다

1)함수 리터럴

아래 코드에서 add에 해당하는 함수 이름은 생략 가능합니다.


function add(x, y){

return x + y;

}


2)함수 선언문

함수명이 반드시 정의되어 있어야 합니다.


function add(x, y){

return x + y;

}


3)함수 표현식(추천!! 이유는 2번 함수 호이스팅에서 설명하겠습니다.)

아래와 같이 함수에 이름을 만들지 않고 변수에 할당하는 방식을 익명 함수 표현식이라 합니다.

함수 내부에서 재귀적으로 호출할 필요가 있을 때에는 함수에 이름을 붙여주면 됩니다.

여기서 add는 함수 이름이 아닌 익명함수를 참조하는 변수입니다. //함수변수


var add = function (x, y){

return x + y;

};


함수 표현식으로 함수를 생성하는 경우에는 세미콜론을 필수로 사용해야합니다.

이유는 다음과 같은 오류가 발생할 수 있기 때문입니다.


var func = function() {
return 42;
}
(function(){
return 24;
})();


위와 같은 코드가 있을 때 func 함수 표현문 끝에 세미콜론이 없기 때문에 자바스크립트 엔진은 중괄호에서 끝났다고 인식하지 못하고 ()로 감싸진 익명함수 생성 리터럴을 무시하고 ()로 func를 실행하게됩니다.

때문에 그 뒤에 있는 ()는 func의 리턴 값인 42()와 같이 인식하게 되어 오류가 발생합니다.




2.함수 호이스팅


앞에서 함수를 생성하는 여러가지 방법에 대해서 나왔는데 이들 사이에는 동작 방식이 약간 차이가 있습니다.

그중의 하나가 바로 함수 호이스팅(Function Hoisting)입니다. 


add(3, 5);

function add(x, y){
return x + y;
};

add(3, 4);


맨 위에 add(3, 5); 같은 경우에는 아직 함수가 선언되지 않았는대도 불구하고 호출이 가능합니다. 

함수가 위치한 위치에 상관없이 함수 선언문 형태로 정의한 함수의 유효 범위는 코드의 맨 처음부터 시작한다. 

이것을 함수 호이스팅이라고 합니다.


함수 표현식으로 함수를 생성하면 이러한 함수 호이스팅이 일어나지 않는다. 


3.함수도 객체다.


자바스크립트에서는 함수를 일급객체라고 부른다.


1) 프로퍼티를 가질 수 있다.


2) 자바스크립트에서 함수는 값으로 취급된다.

- 리터럴에 의해 생성

- 변수나 배열의 요소, 객체의 프로퍼티 등에 할당 가능

- 함수의 인자로 전달 가능

- 함수의 리턴값으로 리턴 가능

- 동적으로 프로퍼티를 생성 및 할당 가능

*위와 같은 자바스크립트 함수의 특성들을 가지고 있는 객체를 일급객체라고 한다.


3) 함수 객체의 기본 프로퍼티

함수는 객체이므로 함수 객체만의 표준 프로퍼티가 정의되어 있습니다.

대표적으로 arguments, caller, length, name, apply, call, bind이 있습니다.

이들 프로퍼티들은 Function.prototype 객체로 부터 받은 것입니다.


- arguemnts

함수로 전달된 인자값들

- length

인자의 수

- caller

자신을 호출한 함수

- name

함수의 이름

- prototype

prototype 프로퍼티는 _proto_와 다릅니다.

* _proto_ : 자신의 부모 역할을 하는 프로토타입 객체를 가리킨다.


prototype 프로퍼티는 함수가 생성될 때 만들어지며 단지 constructor 프로퍼티 하나만 있는 객체를 가리킵니다.

그리고 prototype 프로퍼티가 가리키는 프로토타입 객체의 constructor 프로퍼티는 자신과 연결된 함수를 가리킵니다.


즉, 자바스크립트에서는 함수를 생성할 때, 함수 자신과 연결된 프로토타입 객체를 동시에 생성하며

이 둘은 prototype 과 constructor라는 프로퍼티로 서로를 가리킵니다.




그러니까 예를들어 func 함수는 생성될 때 프로토타입 객체가 동시에 생성되고 이 객체를 prototype 프로퍼티로 참조합니다. 이 프로토타입 객체는 constructor라는 프로퍼티를 가지고 있고, 이 또한 객체이므로 _proto_ 프로퍼티도 가지고 있습니다.




prototype 프로퍼티가 가리키고 있는 func의 프로토타입객체는 constructor 프로퍼티로 func 함수를 가리킵니다.




이해하기 힘든 개념일 수 있습니다. 이후 프로토타입과 프로토타입 체이닝에 대해서 자세히 포스팅할 예정이니 이정도 책 내용 정도로만 이해하시고 넘어가시면 될 것 같습니다.



4.함수의 다양한 형태


1) 콜백함수

함수를 명시적으로 호출하는 것이 아니라 개발자는 함수를 등록하고, 특정 이벤트가 발생하거나 특정 시점에 도달하였을 때 시스템에서 호출하는 함수를 말합니다.


대표적인 콜백 함수의 사용 예가 자바스크립트에서의 이벤트 핸들러 처리입니다. 웹페이지가 로드 되거나, 키보드 입력되는 등 DOM이벤트가 발생할 경우 브라우저는 정의된 DOM 이벤트에 해당하는 이벤트 핸들러를 실행시킵니다. 개발자가 만약 해당하는 이벤트 핸들러에 콜백 함수를 등록했다면 이벤트가 발생할 때마다 브라우저에 의해 실행되게 됩니다.



2) 즉시 실행 함수

함수를 정의함과 동시에 바로 실행하는 함수를 즉시 실행 함수(immediate functions)라 합니다.

함수가 선언되자마자 실행되게 만든 즉시 실행 함수의 경우 같은 함수를 다시 호출할 수 없습니다. 따라서 최초 한 번의 실행만을 필요로 하는 초기화 코드에 사용할 수 있습니다.

예를 들어 아래와 같은 형태로 사용하실 수 있습니다.

(function(name){
//initialize 함수
console.log("Init");
InitFrame();
InitModel();
InitMain();
user.name = name;
})("song");

그리고 jQuery와 같은 자바스크립트 라이브러리나 프레임워크 소스들에서 사용되니 알아두면 좋습니다.

jQuery에서 즉시 실행 함수를 사용하는 이유는 함수 유효 범위 때문입니다.

*자바스크립트에서 변수는 전역 유효 범위를 가진다. 그러나 함수 내부의 변수(var)는 함수 유효 범위를 가진다.



따라서 라이브러리 코드를 즉시 실행 함수 내부에 정의해두면, 라이브러리 내의 변수들에 외부에서 접근할 수 없습니다. 따라서 즉시 실행 함수 내에 라이브러리 코드를 추가하면 전역 네임스페이스를 더럽히지 않고, 다른 라이브러리들이 동시에 로드 되더라도 라이브러리간 변수 이름 충돌을 방지할 수 있습니다.

3) 내부 함수

함수 내부에 정의된 함수를 내부 함수라고 부릅니다. 내부 함수는 클로저를 생성하거나 부모 함수 코드에서 외부에서의 접근을 막고 독립적인 헬퍼 함수를 구현하는 용도로 사용합니다.


내부 함수의 특징은 다음과 같습니다.

- 내부 함수에서는 자신을 둘러싼 부모 함수의 변수에 접근이 가능하다.

C++과 같은 언어를 사용하셨던 분들은 낯설게 느끼실 수 있습니다. 이러한 것이 가능한 이유는 자바스크립트의 스코프 체이닝 때문입니다.  


*클로저, 스코프 체이닝은 따로 포스팅하겠습니다. ^^



- 내부 함수는 일반적으로 자신이 정의된 부모 함수 내부에서만 호출이 가능하다.


5. 함수 리턴


1) 일반 함수나 메서드는 리턴값을 지정하지 않을 경우, undefined 값이 리턴된다.

2) 생성자 함수에서 리턴값을 지정하지 않을 경우 생성된 객체가 리턴된다.

3) 생성자 함수에서 리턴값을 명시적으로 특정 객체로 지정한 경우 지정된 객체가 리턴된다.

그러나 만약 객체가 아닌 value값을 리턴 하려한다면 무시하고 this로 바인딩된 객체가 리턴됩니다.


다음번 포스팅은 함수와 this에 대한 내용입니다.