[12장] 함수(1)

ssu00·2022년 1월 8일
0

12.1 함수란?

함수는 일련의 과정을 statement로 구현하고, 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다.

function add(x,y){ //함수 정의
	return x+y;
}
add(2,5); //함수 호출

12.2 함수를 사용하는 이유

함수는 코드의 재사용성 측면에서 매우 유용하다. 유지보수의 편의성을 높이고, 코드의 신뢰성과 가독성을 높일 수 있다.

12.3 함수 리터럴

자바스크립트의 함수는 객체 타입의 값이다. 따라서 함수도 함수 리터럴로 생성할 수 있다. 함수 리터럴은 function 키워드, 함수 이름, 매개변수 목록, 함수 몸체로 구성된다.

이때 함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자이며, 생략도 가능하다.

var f = function add(x,y){
        return x+y;
      };

함수는 객체이지만, 일반 객체와는 다르다. 일반 객체는 호출할 수 없지만, 함수는 호출할 수 있다. 또한 일반 객체에는 없는 함수 객체만의 고유한 프로퍼티를 갖는다.

12.4 함수 정의

1) 함수 선언문

function add(x, y) {
  return x + y;
}

함수 선언문은 함수 이름을 생략할 수 없으며, 표현식이 아닌 문이다. 따라서, 함수 선언문은 변수에 할당할 수 없다.

하지만 아래 코드를 보면, 함수 선언문이 변수에 할당되는 것처럼 보인다.

var add = function add(x, y){
	return x + y;
};
console.log(add(2, 5));

이는 자바스크립트 엔진이 코드의 문맥에 따라 동일한 함수 리터럴을 함수 선언문으로 해석할 수도 있고, 함수 리터럴 표현식으로 해석할 수도 있기 때문이다.

함수 선언문과 함수 리터럴 표현식은 호출에 차이가 있다.

function foo() { console.log('foo'); }
(function bar() { console.log('bar'); }); //함수 리터럴을 피연산자로 사용하면 함수 선언문이 아닌 함수 리터럴 표현식으로 해석된다. 

foo(); //foo
bar(); //ReferenceError

foo 함수는 호출이 가능했지만, bar 함수는 호출이 불가능하다. 그 이유는, 함수 몸체 외부에서는 함수 이름으로 함수를 참조할 수 없기 때문이다. (함수 리터럴에서, 함수 이름은 함수 몸체 내에서만 참조할 수 있는 식별자이다.)

2) 함수 표현식
자바스크립트의 함수는 일급 객체이다. 일급 객체란, 값의 성질을 갖는 객체라는 의미이다. 즉, 자바스크립트의 함수는 값처럼 사용할 수 있다.

함수는 일급 객체이기 때문에 변수에 할당할 수 있는데, 이를 함수 표현식이라고 한다. 함수 표현식은 표현식인 문이다.

var add = function foo(x, y){
	return x + y;
};
console.log(add(2, 5)); //7
console.log(foo(2, 5)); //ReferenceError

함수 표현식에서 함수 호출을 할 때에는 함수 이름이 아닌, 함수 객체를 가리키는 식별자를 사용해야 한다. 위에서 말했듯, 함수 리터럴의 함수 이름은 함수 몸체 내부에서만 유효한 식별자이기 때문이다.

함수 생성 시점

console.dir(add); //f add(x, y)
console.dir(sub); //undefined
console.log(add(2, 5)); //7
console.log(sub(2, 5)); //TypeError: sub is not a function
function add(x, y) { return x + y; } //함수 선언문
var sub = function (x, y) { return x - y; }; //함수 표현식

1) 함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점은 다르다.
2) 함수 선언문으로 정의한 함수에는 함수 호이스팅이 발생해 런타임 이전에 함수 선언문이 먼저 실행된다.
3) 하지만 함수 표현식으로 정의한 함수에는 함수 호이스팅이 아닌 변수 호이스팅만 발생한다. 즉, 변수 선언은 런타임 이전에 실행되지만 변수 할당문의 값은 런타임에 평가된다.


3) Function 생성자 함수
자바스크립트가 기본 제공하는 빌트인 함수인 Function 생성자 함수매개변수 목록과 함수 몸체문자열로 전달한다.

var add = new Function ('x','y','return x + y');

하지만 Function 생성자 함수로 생성한 함수는 함수 선언문과 함수 표현식으로 생성한 함수와는 다르게 동작하며, 바람직하지 않다.


4) 화살표 함수(ES6)
function 키워드 대신 화살표를 사용해 함수를 선언한다. 화살표 함수는 항상 익명 함수이다.

var add = (x, y) => x + y;

12.5 함수 호출

1) 매개변수와 인수
함수는 매개변수의 개수와 인수의 개수가 일치하는지 체크하지 않는다. 인수가 할당되지 않은 매개변수의 값은 undefined이다. 매개변수보다 인수가 많은 경우, 초과된 인수는 무시된다.

function add(x, y){
	return x + y;
}
console.log(add(2)); //NaN

2) 인수 확인
자바스크립트는 동적 타입 언어로, 매개변수의 타입을 사전에 지정할 수 없다. 따라서 함수를 정의할 때 적절한 인수가 전달되었는지 확인할 필요가 있다.

function add(x, y){
	if(typeof x !== 'number' || typeof y !== 'number'){
    	throw new TypeError('인수는 모두 숫자 값이어야 합니다.');
   	}
    return x + y;
}

혹은 단축 평가를 이용해 매개변수에 기본값을 할당할 수도 있다.

function add(x, y){
    a = a || 0;
    b = b || 0;
    c = c || 0;
}
console.log(add(1, 2)); //3
console.log(add(2)); //2
console.log(add()); //0

3) 매개변수의 최대 개수
매개변수의 최대 개수에는 제한이 없다. 다만, 최대 3개 이상을 넘지 않는 것을 권장하며 만약 그 이상의 매개변수가 필요하다면 객체 형태로 인수로 전달하는 것이 유리하다. 객체를 인수로 사용하면, 프로퍼티 키만 정확히 지정하면 매개변수의 순서를 신경쓰지 않아도 되기 때문이다.


4) 반환문
반환문은 생략할 수 있으며, 이때 함수는 함수 몸체의 마지막 문까지 실행한 후 암묵적으로 undefined를 반환한다.


0개의 댓글