[Javascript]자바스크립트의 함수

조재권·2021년 6월 24일
0
post-thumbnail

12장 자바스크립트의 함수


출처 모던 자바스크립트 Deep Dive을 보고 정리한 내용입니다.

함수란 일련의 과정을 문으로 구현하고 코드 블럭으로 감싸 하나의 실행단위로 정의한 것을 말한다.

//함수 정의
function add(num1, num2) { //함수 이름을 명명한다. 매개변수로 입력값을 받는다.
	return num1 + num2; //반환값
}

//함수 호출
add(1, 2); //함수 식별자에 인수를 넣어 호출

자바스크립트에서 함수는 객체 타입이다. 따라서 함수도 리터럴로 생성할 수 있다.

함수를 선언문으로 사용할 때 함수의 이름은 생략할 수 없으나 함수 표현식으로 사용된 경우 함수의 이름을 생략할 수 있다. 또한 함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자이다.

함수 정의

함수 정의 방식은 다음과 같다.

  • 함수 선언문

    function add(num1, num2){
      return num1 + num2;
    }
  • 함수 표현식

    var add = function (num1, num2) {	//기명 함수
      return num1 + num2;
    }
    
    var add = function add (num1, num2) { //무명 함수 or 익명 함수
      return num1 + num2;
    }
  • Function 생성자 함수

    var add = new Function('num1', 'num2', 'return num1 + num2');
  • 화살표 함수(ES6)

    var add = (num1, num2) => {
    	return num1 + num2;
    }

함수 선언문

함수 선언문은 표현식이 아닌 문이다. 그러나 함수 표현식에서 변수에 함수의 선언문이 할당되는 것처럼 보인다. 자바스크립트 엔진은 문맥을 통해 함수가 선언문 또는 표현식으로 쓰이는지를 해석한다. 함수선언 또는 함수 표현식에서 사용되는 중괄호 {} 는 블록문으로도 사용되고, 객체 리터럴로도 사용되는 중의적인 표현이다. {}가 단독으로 사용되면 자바스크립트 엔진은 이를 블록문으로 해석하여 함수 선언문으로 인식하고 동작한다. 할당 연산자의 우변과 같이 피연산자로서 사용되는 경우 {}를 객체 리터럴로 인식하여 표현식으로써 동작한다.

function foo() {console.log('foo');}
foo(); //'foo'

(function foo2() {console.log('foo2');});
foo2(); //RefernceError

foo함수는 호출이 가능하고, foo2 함수는 참조에러가 발생한다. 그 이유는 무엇일까?

foo함수는 {}가 단독으로 사용되어 함수 선언문으로써 해석되어 호출이 가능한 것을 알 수 있다. 그러나 foo2는 그룹연산자 () 내에 있기 때문에 자바스크립트 엔진은 이를 표현식으로 해석하였다. 함수 리터럴의 '함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자이다'라는 특징을 기억하고 있을 것이다. 그러므로 함수의 이름인 foo2는 함수 내부에서만 사용이 가능하고, 외부에서 사용가능한 식별자는 정의되지 않았기 때문에 호출할 수 없는 것이다.

foo함수는 어떻게 foo라는 이름으로 호출할 수 있었을까? 함수 선언문으로 함수를 선언하면 자바스크립트 엔진은 암묵적으로 함수 이름으로 식별자를 생성한 후 함수 객체를 할당한다. 즉, 함수를 선언하면 아래와 같은 코드로 동작한다.

var foo = function foo() {
  console.log('hello');
}

함수 표현식

자바스크립트의 함수는 변수에 할당이 가능하고, 프로퍼티의 값이 되거나 배열의 요소가 될 수 있다. 값의 성질을 갖는 객체를 일급객체라고 하며 자바스크립트의 함수는 일급객체이다. 그렇기 때문에 표현식으로 변수에 함수 객체가 할당가능하다.

var add = function(num1, num2) {
	console.log(num1 + num2);
}

add(1, 2); //3

앞서 서술하였듯 함수리터럴에서 함수의 이름은 함수 몸체 내에서만 참조할 수 있는 식별자이기 때문에 다음과 같은 코드는 오류를 발생시킨다.

var add = function foo(num1, num2) {	
  console.log(num1 + num2);
}
foo(1, 2); //TypeError

foo라는 이름을 가진 함수 객체가 값으로써 저장되어 있고, foo 함수 객체 값이 저장된 공간 주소를 add라는 식별자로 가리키고 있다. 그렇기 때문에 foo라는 이름으로 직접 함수에 접근 할 수 없다.

Function 생성자 함수

Function 생성자 함수에 매개변수 목록과 몸체를 전달하면 함수 객체를 생성하여 반환한다.

var add = new Function('num1', 'num2', 'return num1 + num2');

console.log(add(1, 2)); //3

Function 생성자 함수로 정의한 함수는 클로저(closure)를 갖지 않는 등, 함수 선언문이나 표현식으로 생성한 함수와 다르게 동작하기 때문에 주위를 요해야한다.

var add1 = (function() {
  var a = 1;
  
  return function(num1, num2) {
    return num1 + num2 + a;	
  }
}());

console.log(add1(2, 3)); 

var add2 = (function() {
  var a = 1;
  
  return new Function('num1', 'num2', 'return num1 + num2 + a');
}());

console.log(add2(2, 3)); //ReferenceError

화살표 함수

기존 함수보다 표현이 간결해진 것 뿐만 아니라 동작 또한 간소화 되었다. 기존 함수와 this 바인딩 방식, prototype 프로퍼티가 없으며 arguments 객체를 사용하지 않는다.

const add = (num1, num2) => num1 + num2;

console.log(add(1, 2)); //3
profile
프론트엔드 새내기의 발전 일기

0개의 댓글