# 기명함수와 익명함수
console.log(function fuc() {
return "뿩!";
}, ": 기명함수/ 이름이 있는 함수래~");
console.log(function () {
return "뿩!";
}, ': 익명함수/ 이름이 없는 함수래~');
둘다 함수리터럴로 평가되서 함수객체를 참조한다.

기명함수와 익명함수를 함수리터럴로 참조해서 콘솔로찍어보면 저렇게 참조한다.
브라우저에서 console.dir로 보면 명확히 알 수 있다.

브라우저상에서 console.dir로 프로퍼티들을 살펴보면 name을 키로 갖는 프로퍼티에 기명함수는 'fuc'라는 스트링이 값으로 나와있고, 익명함수는 그냥 빈 스트링 ""이 나와있다.
# 함수이름
console.dir(function fuc() {
return "뿩!";
}, ": 기명함수/ 이름이 있는 함수래~");
console.dir(function () {
return "뿩!";
}, ': 익명함수/ 이름이 없는 함수래~');
위에서 브라우저상에서 console.dir로 쳐본 함수객체는 여러 프로퍼티를 가지고있는데, 프로퍼티 키값이 'name'이란곳을 다시 보자.

이게 바로 이 함수객체의 '함수이름'이다. 이 함수이름은 함수내에서만 참조할 수 있다.
# 응? 뭐라고? 함수호출은 함수이름으로 참조하는거 아냐?
const fuc1 = function fuc2() {
console.log("hello fuc");
};
위 코드를 보자. 흔히들 알고있는 함수표현식이랑 비슷한데 좀 다르다?
대충 보기에 fuc1이라는 식별자에 fuc2라는함수선언문을 할당한것처럼 보인다.
저번 '함수리터럴'에 대해서 정확히 구분하였기에 이 것은 fuc1에 함수리터럴이 할당된것이라는걸 알 수 있다.
정확히는 함수리터럴(메모리에 함수객체 값으로 저장됨)을 fuc1에다가 할당하였다.
그럼 저 함수를 호출해보자.
fuc1() //콘솔로 hello fuc이 나온다~
된다?
그럼 fuc2()로도 호출할 수 있을까?
fuc2()
결과는?

fuc2는 정의되지 않았다는 참조에러가 뜬다.
즉 전역스코프에서는 fuc2를 참조할수가 없고 이말인 즉슨 정의되지 않은 식별자라는 거다.
스코프는 상위스코프로 올라가면서 참조값을 찾는데 이건 나중에 스코프에서 포스팅할예정이다.
아무튼 현재 fuc2()로 함수를 호출할수 없다.
그럼 fuc2는 도대체 뭘까?
# 함수객체에서 함수이름의 정확한 의미
const fuc1 = function fuc2() {
console.log("hello fuc");
};
console.dir(fuc1);
위 코드에서 함수객체를 정확히 다시 분석해보자.
브라우저상에서 console.dir로 함수객체를 들여다 보자. 결과는?

함수 이름이 fuc1이 아니다!!
우리는 분명 위 코드에서 fuc1()으로 함수를 호출했고 fuc2()로 호출했을경우 에러가 떴는데?
정확히는 위 함수리터럴의 함수이름은 fuc2는 함수이름이고 함수몸체내에서만 참조할수 있다. fuc1은 저 fuc2의 함수객체를 참조하는 식별자다!
아래코드는 함수 몸체내에서 fuc2를 참조하는것이다. (호출하면 재귀함수 스택오버플로뜨니까 호출은 횟수제한걸고하셈..)
const fuc1 = function fuc2() {
console.log("hello fuc");
console.log(fuc2); //fuc2로 함수몸체내에서 참조할수 있어요~
};

이렇게 함수몸체내에서 함수이름은 참조가 가능하다. 때문에 위 파트에서 함수이름은 함수내부에서만 참조할수 있다고 한거다.
# 그렇다면?? 함수선언문은 뭔데?
- 함수선언문
function fuc() {
console.log("hello fuc");
}
fuc() // hello fuc
console.dir(fuc);

함수선언문으로 정의한 fuc을 console.dir로 쳐봤다.
역시 함수이름이 fuc으로 되어있다. 그런데 함수이름은 함수몸체내에서만 참조할수 있는데
어떻게 상위스코프인 전역스코프에서 fuc()으로 호출이 되었다?
이를 알기위해선 함수객체의 메모리 동작방식을 알아야한다.
# 함수객체의 메모리 저장방식
function fuc() {
console.log("hello fuc");
}
위 코드를 함수선언문이 아닌 함수리터럴로 보자.

이 함수리터럴에서 fuc이란 글자가 위치한부분의 스트링이 함수객체의 name프로퍼티로 지정이 되게 되는것이다.

함수는 객체이고 요렇게 함수객체가 메모리 공간 어딘가에 값으로 저장된다.
# 그렇다면 위 코드가 함수선언문으로 동작하게 된다면?

자바스크립트엔진이 위 코드를 선언문으로 인식한다면 이 그림처럼 동작한다.
프로퍼티 name : fuc인 함수객체에 참조에의한 전달방식으로 연결된 메모리주소1에 fuc이라는 식별자를 '생성'해서 연결해주는것이다.
때문에 우리는 fuc()으로 전역스코프에서 함수를 호출할 수 있는것이다.
함수이름과 함수객체가 연결된 식별자는 엄연히 다른 개념이다라는점이 중요하다.
# 그렇다면 함수 표현식은 함수이름을 어떻게 해줄까?
const fuc = function () {
console.log("hello fuc");
};
console.dir(fuc);
위 코드는 함수표현식으로 정의한 fuc을 console.dir로 쳐본것이다. 결과는?

얘 역시도 함수이름이 fuc으로 정해져있다.
분명 코드상에서 fuc이라는 식별자에 익명함수리터럴을 할당해줬는데? 그럼 함수객체에서 name프로퍼티 이름은 ""빈스트링아니야?
결론적으로 함수표현식또한 자바스크립트엔진이 함수이름을 저렇게 만들어주는거다.
사실 ES6이전에 함수표현식을 익명함수로 넣으면 name프로퍼티 값이 빈스트링 ""였단다..
# 최종적으로
- 함수이름과 함수식별자는 다른 개념이다.
- 함수이름은 함수몸체내에서만 참조할수 있는 식별자다.
- 함수호출은 함수객체가 참조된 식별자/리터럴에 괄호를 붙여서 호출하는것이다~
'javaScript > jsDeepDive' 카테고리의 다른 글
선언문에서 let var const를 빼고 선언한다면? (0) | 2023.05.25 |
---|---|
함수 호이스팅 (0) | 2023.05.23 |
함수 리터럴에 대해서 (0) | 2023.05.16 |
primitive타입, object타입 mutable(변경가능함) (0) | 2023.05.13 |
자바스크립트가 숫자데이터를 저장하는 방식 // 64비트 부동소수점 (2) | 2023.05.08 |