-
객체로서의 함수와 기명 함수 표현식프로그래밍/Js 2021. 7. 2. 19:50
https://ko.javascript.info/function-object
를 보고 공부한 내용을 정리.1. 객체로서의 함수
함수의 자료형은 객체이다.
그래서 함수를 호출할 수 있을 뿐 아니라 객체처럼 함수에 프로퍼티를 추가, 제거할 수 있다.
1. 'name' 프로퍼티
'name' 프로퍼티를 사용하면 함수이름을 가져올 수 있다.
function sayHi() { alert("Hi"); } alert(sayHi.name); // sayHi
기본값을 사용해서 이름을 할당한 경우.
function f(sayHi = function() {}) { alert(sayHi.name); // sayHi (이름이 있네요!) } f(); //(코드가 참 희한하게 생겼다)
객체 메서드 이름은 함수처럼 자동할당이 되지 않는다. 이름을 알 수 없는 경우가 있는데, 아래와 같다.
// 배열 안에서 함수를 생성함 let arr = [function() {}]; alert( arr[0].name ); // <빈 문자열> // 엔진이 이름을 설정할 수 없어서 name 프로퍼티의 값이 빈 문자열이 됨
2. 'length' 프로퍼티
내장 프로퍼티 length는 함수 매개변수의 개수를 반환한다.
function f1(a) {} function f2(a, b) {} function many(a, b, ...more) {} alert(f1.length); // 1 alert(f2.length); // 2 alert(many.length); // 2
마지막 many함수를 통해서, 나머지 매개변수는 개수에 포함되지 않는다.
다음도 비슷한 예시이다.
function ask(question, ...handlers) { let isYes = confirm(question); for(let handler of handlers) { if (handler.length == 0) { if (isYes) handler(); } else { handler(isYes); } } } // 사용자가 OK를 클릭한 경우, 핸들러 두 개를 모두 호출함 // 사용자가 Cancel을 클릭한 경우, 두 번째 핸들러만 호출함 ask("질문 있으신가요?", () => alert('OK를 선택하셨습니다.'), result => alert(result));
3. 커스텀 프로퍼티
함수에 자체적으로 만든 프로퍼티를 추가할 수 있다. 단, 프로퍼티는 변수가 아니다. 아래와 같이 sayHi.counter = 0으로 함수에 프로퍼티를 할당해도, 함수 내에 counter라는 지역변수가 생성되는 것은 아니다.
function sayHi() { alert("Hi"); // 함수를 몇 번 호출했는지 세봅시다. sayHi.counter++; } sayHi.counter = 0; // 초깃값 sayHi(); // Hi sayHi(); // Hi alert( `호출 횟수: ${sayHi.counter}회` ); // 호출 횟수: 2회
클로저는 함수프로퍼티로 대체할 수 있다.
function makeCounter() { // let count = 0 대신 아래 메서드(프로퍼티)를 사용함 function counter() { return counter.count++; }; counter.count = 0; return counter; } let counter = makeCounter(); alert( counter() ); // 0 alert( counter() ); // 1
count는 외부 렉시컬 환경이 아닌 함수 프로퍼티에 바로 저장된다. 하지만 클로저를 사용하지 않고, 함수 프로퍼티를 사용하였기 때문에, 아래처럼 외부 렉시컬환경에서 값을 변경할 수 있다.
function makeCounter() { function counter() { return counter.count++; }; counter.count = 0; return counter; } let counter = makeCounter(); counter.count = 10; alert( counter() ); // 10
4. 기명 함수 표현식
기명함수 표현식은 이름이 있는 함수 표현식을 가리키는 용어이다.
let sayHi = function func(who) { alert(`Hello, ${who}`); };
func이라는 이름을 붙이면 두 가지의 변화가 있다.
1. 이름을 사용해서 함수 표현식 내부에서 자기자신을 참조할수 있음
2. 기명함수 표현식 외부에서는 그 이름을 사용할 수 없다.
let sayHi = function func(who) { if (who) { alert(`Hello, ${who}`); } else { func("Guest"); // func를 사용해서 자신을 호출합니다. } }; sayHi(); // Hello, Guest // 하지만 아래와 같이 func를 호출하는 건 불가능합니다. func(); // Error, func is not defined (기명 함수 표현식 밖에서는 그 이름에 접근할 수 없습니다.)
여기서 의문이 드는 것이, 뭐하러 func을 쓰냐는 것이다. 그냥 sayHi로 다시 자기자신을 호출하면 안되나??
만약, sayHi()로 자기자신을 호출한다면, 외부 코드에 의해 sayHi가 변경 된다면, 예상치 못한 에러가 발생할 수도 있다.
let sayHi = function(who) { if (who) { alert(`Hello, ${who}`); } else { sayHi("Guest"); // TypeError: sayHi is not a function } }; let welcome = sayHi; sayHi = null; welcome(); // 중첩 sayHi 호출은 더 이상 불가능합니다!
함수 선언문에서는 내부 이름을 지정할 수 없다.
요약
함수는 객체이다.
따라서, 프로퍼티를 추가할 수 있다.
대표적인 내장 프로퍼티는 name, length가 있다.
커스텀 프로퍼티를 잘 활용한다면, 전역 변수가 많이 줄어들 것이다. 당연히, 그러면 이름 충돌도 방지 된다.
커스텀 프로퍼티를 만들면 함수는 자기자신을 이용해 원하는 일을 수행 할 수 있다.
'프로그래밍 > Js' 카테고리의 다른 글
call/apply와 데코레이터, 포워딩 (0) 2021.07.20 new Function 문법 (0) 2021.07.05 JS-객체 (0) 2021.05.12 JS - 추상관계비교 (0) 2021.02.24 JS-parseInt 문자열→숫자로 파싱 (0) 2021.02.22