sharingStorage

모던 자바스크립트 12장 함수 본문

Front-End/모던 자바스크립트 Deep Dive

모던 자바스크립트 12장 함수

Anstrengung 2022. 6. 13. 13:22

12장 함수

 

12.4.1 함수 선언문

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

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

console.log(add1(1,2)); // 3 식별자인 add1으로 함수를 호출한다.

 

12.4.3 함수 생성 시점과 함수 호이스팅

console.log(add(2,4)); // 6
console.log(sub(3,1)); // TypeError: sub is not a function

//함수 선언문
function add (x,y){
	return x+y;
}

//함수 표현식
var sub = function(x,y){
	return x-y;
}

위 예제와 같이 함수 선언문으로 정의한 함수는 함수 선언문 이전에 호출할 수 있지만 함수 표현식으로 정의한 함수는 함수 표현식 이전에 호출할 수 없다.

이는 함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성시점이 다르기 때문이다.

 

모든 선언문이 그렇듯 함수 선언문도 코드가 한 줄씩 순차적으로 실행되는 시점인 런타임 이전에 자바스크립트 엔진에 의해 먼저 실행된다. 

이처럼 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 함수 호이스팅이라고 한다.

 

일전에 봤던 변수 호이스팅과는 약간의 차이가 있는데 var키워드를 사용한 변수는 undefined로 초기화 되고 함수 선언문을 통해 생성된 식별자는 함수 객체로 초기화된다. 

 

함수 표현식은 변수에 할당되는 값이 함수인 리터럴문이고 변수 선언문과 변수 할당문을 한번에 기술한 축약표현과 동일하게 동작한다.

변수 할당문의 값은 할당문이 실행되는 시점, 즉 런타임에 평가되므로 함수 표현식의 함수 리터럴도 할당문이 실행되는 시점에 평가되어 함수 객체가 된다.

따라서 함수 표현식은 변수 호이스팅이 발생한다.

 

함수 호이스팅은 함수를 호출하기 전에 반드시 함수를 선언해야한다는 당연한 규칙을 무시하고 이와 같은 문제 때문에 함수 선언문 대신 함수 표현식을 사용할 것을 권장한다.

 

12.4.5 화살표 함수

화살표함수는 표현뿐만 아니라 내부 동작 또한 간략화 되어 있다.

간단히 알아보자면 화살표 함수는 생성자 함수로 사용할 수 없으며 기존 함수와 this 바인딩 방식이 다르고, prototype 프로퍼티가 없으며 arguments 객체를 생성하지 않는다.

 

 

12.5.3 매개변수의 최대 개수

ECMAScript 사양에서는 매개변수 최대 개수를 제한하고 있지 않지만 매개변수는 적을수록 좋고(매개변수가 많다는 것은 함수가 여러가지 일을 한다는 증거) 함수 외부에서 내부로 전달한 객체를 함수 내부에서 변경하면 함수 외부의 객체가 변경되는 부수 효과 (side effect)가 발생하므로 주의해야한다.

 

 

12.6 참조에 의한 전달과 외부 상태의 변경

원시 값은 값에 의한 전달, 객체는 참조에 의한 전달 방식으로 동작한다. 

매개변수 역시 타입에 따라 위 두개의 방식을 따른다.

function changeVal(primitive, obj) {
	primitive +=100;
    obj.name='Kim';
}

var num =100;
var person= {name= 'Lee'};

changeVal(num, person);


// 원시 값은 원본이 훼손되지 않는다.
console.log(num); // 100 

// 객체는 원본이 훼손된다.
console.log(person); // {name: "Kim"}

함수 외부에서 함수 몸체 내부로 전달한 원시 값의 원본을 변경하는 어떠한 부수효과도 발생하지 않지만

객체 타입 인수는 참조 값이 복사되어 매개변수에 전달되기 때문에 함수 몸체에서 참조 값을 통해 객체를 변경할 경우 원본이 훼손된다. 즉 부수효과가 발생한다.

 

이는 원시 값과 다르게 객체가 변경할 수 있는 값이며 참조에 의한 전달 방식으로 동작하기 때문에 발생하는 부작용이다. 

객체의 변경을 추적하려면 Observer 패턴 등을 통해 객체의 참조를 공유하는 모든 이들에게 변경을 통지하고 대처하는 대응이 필요하다.

 

이러한 문제의 해결 방법은 객체를 immutable한 객체로 만들어 사용하는 것인데 객체의 상태 변경이 필요한 경우에는 깊은 복사 (deep copy)를 통해 새로운 객체를 생성하고 재할당을 통해 교체한다. 이는 부수효과(side effect)를 없애는 방법이다.

12.7.4 콜백함수

함수의 일부분만 다를 때 매번 함수를 새롭게 정의해야하는 문제는 콜백함수를 사용함으로서 해결할 수 있다.

콜백함수 사용 예

위의 예시처럼 함수의 변하지 않는 공통 로직은 미리 정의해두고, 경우에 따라 변경되는 로직은 추상화하여 함수 외부에서 내부로 전달하는 것이다.

이처럼 함수의 매개변수를 통해서 다른 함수의 내부로 전달되는 함수를 콜백 함수라고 하며 매개변수를 통해 함수의 외부에서 콜백함수를 전달받은 함수를 고차함수라고 한다.

 

고차함수는 콜백 함수를 자신의 일부분으로 합성하며 고차 함수는 매개변수를 통해 전달받은 콜백 함수의 호출 시점을 결정해서 호출한다.

 

콜백 함수는 함수형 프로그래밍 패러다임뿐만 아니라 비동기 처리(이벤트 처리, Ajax통신, 타이머 함수 등)에 활용되는 중요한 패턴이다.

 

콜백 함수를 사용하는 고차 함수

위의 예시는 콜백 함수를 사용하는 고차함수들의 모습이다.

map 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다.

filter 메서드는 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다

reduce 메서드는 각 요소에 주어진 reducer함수를 실행하고 하나의 값을 반환합니다.

 

12.7.5 순수 함수와 비순수 함수

외부 상태를 변경하지 않고 외부 상태에 의존하지 않는 함수를 순수함수라 하는데 순수함수를 통해 부수효과를 최대한 억제하고 프로그램의 안정성을 높이는 프로그래밍 패러다임을 함수형 프로그래밍이라고 한다.

 

순수함수는 일반적으로 최소 하나의 인자를 전달받는다.

순수함수는 인수의 불변성을 유지하고 함수의 외부 상태를 변경하지 않는다.

순수함수는 동일한 인수를 전달받으면 언제나 동일한 값을 반환하는 함수이다.

순수함수의 예시

 

비순수 함수는 함수 외부 상태에 따라 반환값이 달라지는 함수이며 외부 상태를 변경하는 부수효과가 있다.

비순수 함수 예시

위와 같은 비순수 함수는 코드의 복잡성을 증가시키고 부수효과가 발생한다.

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

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

Comments