티스토리 뷰

반응형

자바스크립트는 함수형 언어다. 

함수형 언어에서의 함수는 유연하다. 언제든지 정의할 수 있고 언제든 제거도 가능하다. 


'유연한 함수'라는 것의 예로는 익명 함수를 들 수 있다. 

익명 함수는 함수를 변수에 저장하거나, 콜백 함수로 등록하는 경우 사용되는 '이름이 없는 함수'다.


window.onload = function() {

console.log("안녕안녕~~");

}


var obj = {

speak : function() {

console.log("내 이름은 김김이야");

}

}


obj.speak();


setTimeout(function() {

console.log("만나서 반가워융");

}, 1000)


위의 예시에서 볼 수 있듯이, 

이벤트 실행 시, 객체의 메소드 실행 시, setTimeout 함수의 콜백 실행 시 

이름이 없는 익명 함수가 실행되는 예시를 확인해볼 수 있다. 


재귀 함수 예시를 통해 익명 함수를 활용하는 방법과 함수의 특징을 자세히 들여다 보자.

(재귀 함수란, 자신이 자신을 호출하는 구조로 되어 있는 함수)


다음 예시는 간단하게 작성해 본 재귀 함수다. 


function chirp(n) {

return n > 1 ? chirp(n - 1) + "-chirp" : "chirp";

}


console.log(chirp(3)); // chirp-chirp-chirp


- 이름을 이용해 참조하기


위의 예시를 메소드 호출로 수정할 수 있다. 

다음은 위의 코드를 메소드 호출로 실행하는 예시 코드다.


var ninja = {

chirp: function(n) {

return n > 1 ? ninja.chirp(n-1) + "-chirp" : "chirp";

}

}


console.log(ninja.chirp(3)); // chirp-chirp-chirp


위의 코드는 ninja라는 객체의 chirp 메소드를 호출하고 있다. 

이 때, ninja 객체의 chirp 메소드가 사라지게 되면 어떻게 될까??


- 객체의 프로퍼티명을 통해 메소드 참조하기


var ninja = {

chirp: function(n) {

return n > 1 ? ninja.chirp(n-1) + "-chirp" : "chirp";

}

}


var ninja2 = {

chirp : ninja.chirp

};


ninja = {};


console.log(ninja2.chirp(3)); // Uncaught TypeError: ninja.chirp is not a function


ninja2 객체의 chirp 변수에 ninja의 chirp 메소드를 대입하였지만,

ninja 객체 값을 변경함에 따라서 ninja2의 chirp 메소드도 실행하지 못하게 되었다. 


이유가 무엇일까? 


ninja2.chirp와 ninja.chirp는 동일한 익명 함수를 가리키고 있었다.

또한 익명 함수는 재귀 호출하는 부분의 경우 ninja 객체를 참조하고 있다. 


// ninja2.chirp와 ninja.chirp가 가리키는 익명 함수

function(n) {

return n > 1 ? ninja.chirp(n-1) + "-chirp" : "chirp"; // ninja 객체를 참조하고 있다. 

}


두 개의 메소드가 하나의 익명 함수를 가리키는 부분은 문제가 없다. 

문제는 ninja 객체를 새로운 값으로 재할당을 하게되면서 발생하게 된다. 


ninja 객체에 비어 있는 값으로 새롭게 값을 할당을 하게되면서,

ninja.chirp 프로퍼티 값은 존재하지 않는 값이 되었다. 

이로써 재귀 함수가 호출되는 부분(ninja 객체가 참조되는 부분)에서 에러가 발생하게 되는 것이다. 


그렇다면 어떻게 문제랄 해결할 수 있을까??

재귀 함수가 호출되는 부분에서 특정 객체를 참조하지 않고

자기 자신을 참조하도록 수정해보자.


var ninja = {

chirp: function(n) {

return n > 1 ? this.chirp(n-1) + "-chirp" : "chirp";

}

}


var ninja2 = {

chirp : ninja.chirp

};


ninja = {};


console.log(ninja2.chirp(3)); // chirp-chirp-chirp


메소드의 this는 해당 메소드의 객체를 가리키므로, 

특정 객체를 참조하지 않고 자신을 참조하여 chirp 메소드를 호출하도록 변경하여 문제가 해결이 된다. 


위의 상황은 메소드 명이 chirp라는 것을 가정한 경우에 대한 해결 방법이다.

하지만 만약 메소드의 이름이 chirp가 아니면 어떻게 될까??


다음은 객체의 프로퍼티 값과 무관하도록 

메소드에 이름을 지정하여 프로퍼티의 값이 다르더라도 실행할 수 있도록 변경한 방법이다.


- 인라인 함수 활용하기


다음과 같이 익명 함수에 이름을 지정하는 함수를 인라인 함수라고 한다.


var ninja = {

chirp: function signal(n) {

return n > 1 ? signal(n-1) + "-chirp" : "chirp";

}

}


var ninja2 = {

chirp : ninja.chirp

};


ninja = {};


console.log(ninja2.chirp(3)); // chirp-chirp-chirp


위의 예제에서는 chirp 메소드와 signal 메소드는 동일한 함수를 가리킨다.
즉 함수의 이름이 signal, chirp 두 개인 셈이다. 

하지만, 인라인 함수의 이름 (signal)은 외부에서 접근할 수가 없다. 
인라인 함수의 이름은 해당 함수 안에서만 유효하다. 
아래의 예시를 통해서 직접 확인할 수 있다. 

var ninja = {
chirp: function signal(n) {
return n > 1 ? signal(n-1) + "-chirp" : "chirp";
}
}
console.log(typeof ninja.chirp) // function
console.log(typeof ninja.signal) // undefined

위의 예시에서 확인할 수 있듯이,
typeof 연산자를 통해 객체가 함수 인스턴스인지 확인할 수 있다. 
(결과 값이 'function'이면 함수의 인스턴스)


- 함수 내부 프로퍼티 활용하기 


함수 자체의 프로퍼티를 통해서 재귀 호출을 해결할 수 있다. 

함수는 arguments와 callee라는 프로퍼티를 갖고 있다. 


function func(arg1, arg2) {

// [Object, Object, Object,callee: function, Symbol(Symbol.iterator): function] ...

console.log('arguments', arguments); 

console.log('callee', arguments.callee); 

/*

function func(arg1, arg2) {

console.log('arguments', arguments);

console.log('callee', arguments.callee);


console.log('arg1 : ', arg1, 'arg2 :', arg2);

}

*/


console.log('arg1 : ', arg1, 'arg2 :', arg2); // arg1 :  Object {age: 100} arg2 : Object {weight: 200}

}


func({age: 100}, {weight: 200}, {height: 300});


위의 예에서 확인할 수 있듯이,

arguments는 호출된 함수의 파라미터 등 호출된 함수의 상태 정보를 갖고 있다. 

arguments 프로퍼티 안에 있는 callee 프로퍼티는 현재 실행 중인 함수 내용을 갖고 있따. 


위의 함수 내부 프로퍼티를 활용하여 재귀함수를 작성하게 되면 다음과 같이 될 것이다. 

var ninja = {

chirp: function (n) {

return n > 1 ? arguments.callee(n-1) + "-chirp" : "chirp";

}

}


console.log(ninja.chirp(3)); // chirp-chirp-chirp


이와 같이 자바스크립트의 함수는 다른 언어의 함수와 다르다. 

함수 자체의 프로퍼트가 존재하며, 변수에 함수를 할당이 가능하며

할당된 변수를 통해 함수 호출 또한 가능하다. 



반응형

'정리하기 > 닌자비급' 카테고리의 다른 글

Chapter5. 클로저와 가까워지기  (0) 2017.06.05
Chapter3. 함수가 핵심이다  (0) 2017.05.25
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함