함수를 정의하는 4가지 방식 중 🔑함수선언문과 🔑함수 🔑생성자 함수 🔑화살표 함수에 대해서
- WHAT IS❓ 함수 정의란 함수를 호출하기 이전에 인수를 전달받을 매개변수와 실행 문들 그리고 반환값을 지정하는 것을 말한다.
- 정의된 함수는 자바스크립트 엔진에 의해 평가되어
함수 객체가 된다.
- 모두 함수를 정의하는 면에서 동일하지만 미묘하지만 중요한 차이가 있으니 그 차이에 대해서 잘 알아야한다...!
1. 함수 선언문
<script> function add(x,y){ return x+y; } </script>
2. 함수 표현식
<script> const add = function(){ return x+y; } </script>
3. Function 생성자 함수
<script> const add = new Function('x', 'y', 'return x+y'); </script>
4. 화살표 함수
<script> const add = (x, y) => x+y; </script>
- 함수 선언문은 함수 리터럴과 형태가 동일하지만
함수 선언문은 함수 이름을 생략할 수 없다.- 함수 선언문은 표현식이 아닌 문이다.
<script> //함수 선언문, 함수명 생략할 수 없다는 것에 주의! function add(x,y){ return x+y; } //함수 참조 console.dir(add)// f add(x, y) , dir은 함수의 객체의 프로퍼티까지 출력해주는 명령어 //함수 호출 console.log(add(2, 5))// 7 </script>
Q. 함수 선언문은 표현식이 아닌 문인데 변수에 할당이 되는 것처럼 동작한다?
<script> //함수 선언문, 변수에 할당하는 것처럼 보인다?! cosnt add = function add(x,y){ return x+y; } //함수 호출 console.log(add(2, 5))// 7 </script>
A. 이유는 자바스크립트 엔진이 코드의 문맥에 따라 기명 함수 리터럴을 두 가지의 경우로 나눠서 해석한다.
1. 표현식이 아닌 문인함수 선언문
으로 해석하는 경우
2. 표현식인 문인함수 리터럴 표현식
으로 해석하는 경우<script> //함수 이름이 있는 기명 함수 리터럴은 해석될 가능성이 2가지 // 1. 함수 리터럴을 단독으로 사용 => 함수 선언문으로 해석 function funcDeclare(){ console.log('나는 함수 선언문으로 해석'); } funcDeclare(); //2. 함수 리터럴 값을 평가되는 문맥(변수 할당) => 함수 리터럴 표현식으로 해석 // 함수 리터럴에선 함수 이름 생략 가능 (function fucLiteral() { console.log('나는 함수 리터럴 표현식으로 해석')}; ); </script>
- 기명 함수는 함수 리터럴을 단독으로 사용하면
함수 선언문
으로 해석하고,- 함수 리털럴이 값으로 평가되어야 하는 문맥(함수 리터럴을 변수에 할당하거나 피연산자로 사용)에선
함수 리터럴 표현식
으로 해석한다.
Q. 함수 선언문과 함수 리터럴 표현식에는 어떤 차이가 존재하할까?
<script> //1. 기명함수로 리터럴을 단독으로 사용 => 함수 선언문 function foo(){console.log('foo')}; foo(); // foo //2. 함수 리터럴 값을 평가되는 문맥(피연산자로 사용) => 함수 리터럴 표현식으로 해석 (function bar(){console.log('bar')};); bar(); // 참조 오류발생 </script>
A. 모두 함수가 생성되는 건 동일하지만 바로 호출의 차이가 발생한다. 위코드를 가지고 설명하겠다.
함수 선언문
으로 생성된 함수foo()
는 호출할 수 있으나
함수 리터럴 표현식
으로 생성된 함수bar()
는 호출 할 수 없다.
-함수 리터럴의 함수의 이름은 오직 함수 몸체 내에서만 참조할 수 있는 식별자이다.
-> 이는 현재 함수bar
를 가리키는 식별자가 없는 상태이기에bar
함수를 호출 할 수 없다.
foo
는 어떻게 이름으로 호출 한거영..❓❓❓❓foo
는 자바스크립트에 엔진이 암묵적으로 생성한 식별자이기 때문에 가능다구...❕❕❕❕
- 자바스크립트 엔진은 함수 선언문을 해석해 함수 객체를 생성하고 함수 이름과 동일한 이름의 식별자를 만든다.
- 이때 함수 이름은 함수 몸체 내부에서만 유효한 식별자이므로 함수 객체를 참조하기 위해서는 함수 객체를 가리키는 식별자가 필요하다.
- 따라서 자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 '암묵적으로 생성하고 거기에 '함수 객체를 할당'한다.
- 따라서
함수 선언문
의 의사코드는 다음과 같아진다.<script> //함수 선언문 cosnt add = function add(x,y){//함수 객체를 참조하기 위해 함수이름과 같은 식별자 생성 후 함수 객체를 할당 return x+y; } //함수 호출은 함수 이름이 아닌 함수 객체를 가리키는 식별자자라는 것의 주의!! console.log(add(2, 5))// 7 </script>
-함수는 함수 이름으로 호출하는 것이 아니라
함수 객체를 가리키는 식별자로 호출한다.
->자바스크립트 엔진은함수 선언문
을함수 표현식
으로 변환해 함수 객체를 생성한다고 생각할 수 있다.
하지만 선언문과 표현식이 정확히 동일하게 동작하지는 않는다.
- 값처럼 자유롭게 사용할 수 있는 일급객체인 함수는 함수 리터럴로 생성한 함수 객체를 변수에 할당할 수 있는데 이러한 함수 정의 방식을 함수 표현식이라 부른다.
<script> //함수 선언문 function add(x,y){ return x+y; } console.log(add(2, 5))// 7 //함수 선언문으로 정의한 add함수를 함수 표현식으로 바꾸어 정의 const add = function (x, y){ return x+y; } //함수 호출 console.log(add(2, 5))// 7 </script>
Q. 함수 표현식의 함수 리터럴에 함수 이름을 붙일 수도 생략할 수 있다고?
<script> //함수 이름이 있는 기명 함수 표현식 const add = function foo(x,y){ return x+y; } // 함수 객체를 가리키는 식별자로 호출해야한다. console.log(add(2, 5))// 7 //함수 이름이 없는 익명 함수 표현식 const add = function (x, y){ return x+y; } //함수 호출 console.log(add(2, 5))// 7 </script>
A. 함수 표현식은
익명 함수 표현식
과기명함수 표현식
으로 나뉜다.
- 함수 표현식의 함수 리터럴의 함수 이름을 생략한
익명 함수 표현식
를 사용하는 것이 일반적이다.익명 함수 표현식
은 함수에 식별자가 주어지지 않고기명함수 표현식
은 함수의 식별자가 존재한다.
- 함수 생성 시점과 호이스팅에서 미묘한 차이가 있음을 인지!
함수 선언문
으로 정의한 함수와함수 표현식
으로 정의한 함수의 생성시점이 다르다.
함수 선언문
- 표현식이 아닌 문으로 호이스팅의 영향을 받아 어디서든 호출이된다.함수 표현식
- 표현식인 문으로 호이스팅에 영향을 받지 않아 함수 코드에 도달해야 생성되고 호출이 된다.<script> console.dir(sayHi);//참조 가능 console.dir(sayHello);//참조 불가능 sayHi()//호출 가능 sayHello()//호출 불가능 //함수 선언문으로 만든 함수 sayHi() // 호이스팅 -> 호출 가능 function sayHi(){ console.log('hi'); } //함수 표현식으로 만든 함수 const sayHello() = function sayHi(){ // 해당 코드에 도달해야 생성되고 console.log('hi');// 코드 도달 후 사용할 수 있다. } // 여기선 호출과 참조가 가능하다 </script>
-함수 선언문
- 모든 선언문이 그렇듯
함수 선언문
역시 1>런타임 이전에 먼저 실행되어 함수 객체를 생성하고 함수 이름과 동일한 식별자에 할당까지 완료된 상태이다.- 따라서
함수 선언문
으로 정의한 함수는 선언문 이전에도
2>함수 호이스팅에 의해 호출과 참조가 가능하다.- 이렇게
함수 선언문
이 코드의 선두로 끌어 올려진 것처럼 동작하는 것, '함수 호이스팅'이라고 한다.
-함수 표현식
함수 표현식
은 변수 선언문과 변수 할당문을 한 번에 기술한 축약 표현과 동일하게 동작한다.- 변수 할당문의 값은 할당문이 실행되는 시점인 런타임에 평가되듯이
함수 표현식
의 함수리터럴도 1>할당문이 시행되는 시점에 평가되어 함수 객체가 된다.- 따라서
함수 표현식
으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 2>변수 호이스팅 발생한다
- WHAT IS❓ 생성자 함수란 객체를 생성하는 함수를 말한다.
객체를 생성하는 방식에 객체 리터럴 방식 이외에 다양한 방법이 있다.
HOW TO USE❕❓ - 자바스크립트가 기본 제공하는 빌트인 함수인 Function 생성자 함수에 매개변수 목록과 함수 몸체를 문자열로 전달하면서 new연산자(없어도 가능)와 함께 호출하면 함수객체를 생성해서 반환한다.
<script> //생성자 함수 const add = new Function('x', 'y', 'return x + y'); //함수 호출 console.log(add(2, 5))// 7 </script>
- Function 생성자 함수로 생성하는 함수는 클로저를 생성하지 않는 등 함수 선언문이나 표현식으로 생성한 함수와 다르게 동작한다.
<script> //함수 선언문 시 클로저 const add1 =(function (){ const a = 10; return function (x, y){ return x + y; }; }()); console.log(add1(1,3)) // 13 //생성자 함수시 클로저 const add2 =(function (){ const a = 10; return new Function('x', 'y', 'return x+y'); }()); console.log(add2(1,3)) // 변수 a참조 오류? </script>
- WHAT IS❓ 화살표 함수란 함수 선언시 함수 표현과 내부 동작을 간략화 한 것이다.
- HOW TO USE❕❓ 화살표 함수는 함상 익명함수로 정의한다.
- 화살표 함수는 function 키워드 대신 화살표를 사용해 더 간략한 방법으로 함수를 선언한다.
<script> //화살펴ㅛ 함수 const add = (x, y) => x + y; //함수 호출 console.log(add(2, 5))// 7 </script>
- 생성자함수로는 화살표함수를 사용할 수 없고
기존의 함수와 this 바인딩 방식이 다르고 prototype 프로퍼티가 없으며 arguments 객체를 생성하지 않는다.
함수 선언문
과함수 표현식
의 미묘한 차이, 실행시점과 호이스팅에 대해서 잘 알아두잡!- 함수 호이스팅은 함수를 호출하기 전에 반드시 함수를 선언하는 규칙을 무시하므로
함수 선언문
대신함수 표현식
을 주로 이용하도록하장!
- 책 - 딥다이브 자바스크립트