본문 바로가기

JavaScript

[JS] 모던 자바스크립트 - 07. 함수

728x90
반응형

함수


- 일련의 과정을 문(statement)로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것

- 함수 내부로 입력을 전달받는 변수는 매개변수(parameter), 입력을 인수(argument), 출력을 반환값(return value)이라 한다

- 함수는 객체타입의 값, 함수가 객체라는 사실은 다른 프로그래밍 언어와 구별되는 자바스크립트의 중요한 특징

- 함수는 일급객체, 값의 성질을 갖는 객체다

- 함수 이름함수 몸체 내에서만 참조할 수 있는 식별자

- 변수는 선언한다고 하지만, 함수는 정의한다고 한다

- 일반 객체는 호출할 수 없지만 함수는 호출 가능

 

함수 정의


함수 선언문

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

- 함수 이름을 생략할 수 없다

- 표현식이 아닌 문이므로 변수에 할당할 수 없다

- 그룹 연산자( ) 내에 있는 함수 리터럴은 함수 선언문으로 해석되지 않고 함수 리터럴 표현식으로 해석 (그룹 연산자의 피연산자는 값으로 평가될 수 있는 표현식이어야하기 때문, 함수 선언문은 피연산자로 사용 불가)

- 함수 몸체 외부에서는 함수 이름으로 함수를 호출할 수 없음

( function bar() {console.log('bar'); });
bar(); // RefereceError : bar is not defined

- 자바스크립트 엔진은 함수 선언문을 해석해 런타임 이전에 함수 객체를 생성

- 함수 선언문으로 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고 거기에 함수 객체를 할당

- 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출

- 함수 선언문 이전에 호출해도 함수 호이스팅에 의해 호출 가능

 

함수 표현식

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

 

- 함수 리터럴로 생성한 함수 객체는 표현식인 문이므로 변수에 할당 가능

- 함수 리터럴의 함수 이름은 생략 가능(익명 함수)

- 런타임에 함수 리터럴이 변수에 할당되는 시점에 평가되어 함수 객체가 됨

- 함수 호이스팅이 아닌 변수 호이스팅이 발생

- 함수 표현식 이전에 함수 참조시 undefined로 평가되어 TypeError 발생

- 함수 선언문보다 함수 표현식을 사용하는 것이 좋음

 

Function 생성자 함수

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

- 일반적이지 않고 바람직하지도 않음

- 클로저를 생성하지 않는 등 함수 선언문이나 함수 표현식으로 생성한 함수와 다르게 동작

 

화살표 함수

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

- ES6에서 도입

- function 키워드 대신 화살표(=>)를 사용

- 항상 익명 함수로 정의

- 기존 함수와 this 바인딩 방식이 다르고, prototype 프로퍼티가 없으며, argument 객체를 생성하지 않음

- 함수 내부에 this가 없고, 접근하려고 할 때 스코프 체인상 가장 가까운 this에 접근

 

함수 호출


매개변수와 인수

- 인수는 값으로 평가될 수 있는 표현식이어야 함, 함수를 호출할 때 지정

- 매개변수는 함수를 정의할 때 선언, 함수 몸체 내부에서 변수와 동일하게 취급

- 매개변수의 스코프(유효 범위)는 함수 내부

- 함수는 매개변수의 개수와 인수의 개수가 일치하는지 체크하지 않음, 에러 발생 X

- 인수가 할당되지 않은 매개변수의 값은 undefined

- 매개변수보다 인수가 더 많은 경우 초과된 인수는 무시, 버려지는 것은 아니고 arguments 객체의 프로퍼티로 보관(arguments 객체는 함수를 정의할 때 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용)

- 자바스크립트는 동적타입 언어로서 매개변수 타입을 사전에 지정 할 수 없음(이 때문에 타입스크립트를 사용)

- ES6의 매개변수 기본값을 사용하면 함수 내부에서 하던 인수 체크 및 초기화를 간소화

function add(a=0, b=0, c=0){
    return a + b + c;
}

- 원시 값의 인수는 부수효과가 없음

- 객체 타입 인수는 함수 내부에서 변경 시 부수효과 발생, 그러므로 객체는 깊은 복사를 통해 새로운 객체를 생성하고 재할당을 통해 교체 

 

반환문

- 함수 호출은 표현식으로 return 키워드가 반환한 표현식의 평가 결과, 즉 반환값으로 평가

- 함수의 실행을 중단하고 함수 몸체를 빠져나감

- return 키워드 뒤에 오는 표현식을 평가해 반환, 표현식을 명시적으로 지정하지 않은 경우 undefined 반환

- 생략 가능, 생략 시 암묵적으로 undefined 반환

- 함수 내부에서만 사용 가능, 전역에서 사용 시 문법 에러(SyntaxError) 발생 (Node.js 환경에서는 파일별로 독립적인 파일 스코프를 갖기 때문에 에러 발생 X)

 

함수의 형태


즉시 실행 함수

- 함수 정의와 동시에 호출되는 함수

// 익명 즉시 실행 함수
(function () {
    var a = 3;
    var b = 5;
    return a * b;
}());

- 익명함수를 쓰는 것이 일반적, 함수 이름을 쓸 순 있지만 그룹 연산자 내에서의 기명함수는 함수 선언문이 아닌 함수 리터럴로 평가되어 외부에서 호출 불가능하므로 불필요함

- 반드시 그룹 연산자(...)로 감싸야함

- 함수 선언문 뒤에 붙이는 ( )는 함수 호출 연산자가 아니라 그룹 연산자로 해석, 그룹 연산자에 피연산자가 없어 에러 발생

- 즉시 실행 함수 내에 코드를 모아두면 변수나 함수 이름의 충돌 방지 가능

 

재귀 함수

- 함수가 자기 자신을 호출하는 재귀 호출을 수행하는 함수

- 반복되는 처리를 반복문 없이 구현 가능

- 함수 이름, 함수 식별자 두가지로 전부 호출 가능

- 재귀 함수 내에 재귀 호출을 멈출 수 있는 탈출 조건을 반드시 만들어야 함, 그렇지 않으면 함수가 무한 호출되어 stack overflow 에러 발생

- 무한 반복에 빠질 위험이 있으므로 반복문보다 재귀함수를 사용하는 것이 직관적으로 이해하기 쉬울 때만 한정적으로 사용하도록 해야함

 

중첩 함수

- 함수 내부에 정의된 함수(inner function)

- 중첩 함수를 포함하는 함수는 외부 함수(outer function)

 

콜백 함수

- 매개변수를 통해 다른 함수의 내부로 전달되는 함수

- 매개변수를 통해 외부에서 콜백 함수를 전달받은 함수는 고차함수

- 고차 함수는 콜백 함수를 자신의 일부분으로 합성

- 고차 함수에 의해 호출되며 콜백 함수에 인수를 전달할 수도 있음

- 함수형 프로그래밍 패러다임과 비동기처리(이벤트 처리, Ajax 통신, 타이머 함수 등)에 활용되는 중요한 패턴

- 배열 고차 함수에서도 사용

 

순수 함수와 비순수 함수

- 순수함수는 부수효과가 없는 함수, 외부 상태를 변경 X

- 비순수 함수는 부수효과가 있는 함수, 외부 상태를 변경, 외부 상태에 의존

- 순수 함수는 동일한 인수가 전달되면 언제나 동일한 값을 반환

- 함수 내부에서 외부 상태를 직접 참조하지 않더라도 매개변수를 통해 객체를 전달 받으면 비순수 함수가 됨

- 함수형 프로그래밍은 순수 함수와 보조 함수의 조합을 통해 외부 상태를 변경하는 부수 효과를 최소화해서 불변성을 지향하는 프로그래밍 패러다임

- 자바스크립트는 멀티 패러다임 언어로, 객체 지향 뿐 아니라 함수형 프로그래밍을 적극적으로 활용

 

 

 

 

 

출처

- 모던 자바스크립트 Deep Dive - 자바스크립트의 기본 개념과 동작 원리
- 코어 자바스크립트 

728x90
반응형