본문 바로가기

JavaScript

[Deep dive] 12장 함수(2)

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

 

- changeVal 함수는 매개변수를 통해 전달받은 원시 타입 인수와 객체 타입 인수를 함수 몸체에서 변경

//매개 변수 primitive는 원시 값을 전달받고, 매개변수 obj는 객체를 전달받음
function changeVal(primitive, obj) {
  primitive += 100;
  obj.name = 'Kim';
}

//외부 상태 
var num = 100;
var person = {name : 'Lee'};

console.log(num); //100
console.log(person); // {name : "Lee"}

//원시 값은 값 자체가 복사되어 전달되고 객체는 참조 값이 복사되어 전달된다.
changeVal(num, person);

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

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

 

원시 값 primitive

 

- 원시 값은 변경 불가능한 값

- 재할당을 통해 할당된 원시 값을 새로운 원시 값으로 교체 

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

 

객체 값 person 

 

- 참조 값이 복사되어 매개변수에 전달되기 때문에 함수 몸체에서 참조 값을 통해 객체를 변경할 경우 원본이 훼손 됨

- 함수 외부에서 함수 몸체 내부로 전달한 값에 의해 원본 객체가 변경되는 부수효과 발생 

 

해결방법

 

1) 옵저버 패턴

 - 객체의 변경을 추적

 - 객체의 참조를 공유하는 모든 이들에게 변경 사실을 통지하고 이에 대처하는 추가 대응 필요 

 

2) 불변 객체 (immutable object)

 - 객체의 상태 변경을 원천 봉쇄

 - 객체의 상태 변경이 필요한 경우 객체의 방어적 복사(defensive copy)를 통해 새로운 객체를 생성하고 재할당을 통해 교체

 

 

12.6 다양한 함수의 형태 

 

12.6.1 즉시 실행 함수 

 

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

- 단 한번만 호출되며 다시 호출 불가 

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

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

- 즉시 실행 함수는 반드시 그룹 연산자 (..)로 감싸야 함

- 즉시 실행 함수 내에 코드를 모아 두면 혹시 있을 수도 있는 변수나 함수 이름의 충돌을 방지할 수 있음

 

12.6.2 재귀 함수 

 

재귀 호출(recursive call)

- 함수가 자기 자신을 호출하는 것

 

재귀 함수(recursive function)

- 재귀호출을 수행하는 함수 

- 반복되는 처리를 위해 사용

 

ex) 팩토리얼

//팩토리얼은 1부터 자신까지의 모든 양의 정수의 곱
function factorial(n) {
  //탈출 조건 : n이 1이하일 떄 재귀 호출을 멈춤
  if(n<=1) return 1;
  //재귀 호출
  return n*factorial(n-1);
}

console.log(factorial(5)); //5!=5*4*3*2*1=120

 

- 함수 이름과 식별자를 통해 재귀 호출 가능 

- 함수 외부에서 함수 호출을 할때는 반드시 함수를 가리키는 식별자로 해야함

//함수 표현식
var factorial = function foo(n) {
  //탈출 조건 : n이 1 이하일 때 재귀 호출을 멈춤
  if(n<=1) return 1;
  //함수를 가리키는 식별자로 자기 자신을 재귀 호출
  return n*factorial(n-1);

  //함수 이름으로 자기 자신을 재귀 호출 가능
  //console.log(facorial === foo ); //true
  //return n * foo(n-1);
};

console.log(factorial(5)); //5! = 5*4*3*2*1 = 120

 

12.6.3 중첩 함수 

 

중첩 함수 

- 함수 내부에 정의된 함수 

- 자신을 포함하는 외부 함수를 돕는 헬퍼함수의 역할 

 

외부 함수 

- 중첩함수를 포함하는 함수 

 

- 중첩 함수는 외부 함수 내부에서만 호출 가능

 

 

12.6.4 콜백 함수 

 

- 반복하는 일은 변하지 않고 공통적으로 수행하지만 반복하면서 하는 일의 내용은 다름 

- 함수의 일부분만이 다르기 때문에 매번 함수를 새롭게 정의해야함 

- 내부 로직에 강력히 의존 

//n만큼 어떤 일을 반복한다.
function repeat1(n) {
  //i를 출력한다.
  for(var i = 0; i < n; i++) console.log(i);
}

repeat1(5); 

//n만큼 어떤일을 반복한다.
function repeat2(n) {
  for(var i =0; i<n; i++) {
    //i가 홀수 일때 출력
    if(i%2) console.log(i);
  }
}

repeat2(5);

- 함수의 변하지 않는 공통 로직은 미리 정의해 두고, 경우에 따라 변경되는 로직은 추상화 해서 함수 외부에서 함수 내부로 전달

//외부에서 전달받은 f를 n만큼 반복 호출
function repeat(n,f) {
  for(var i = 0; i < n; i++) {
    f(i); //i를 전달하면서 호출
  }
}

var logAll = function(i) {
  console.log(i);
};

//반복 호출할 함수를 인수로 전달
repeat(5,logAll); //0 1 2 3 4

var logOdds = function (i) {
  if(i % 2) console.log(i);
}

//반복 호출할 함수를 인수로 전달
repeat(5,logOdds); //1 3

- repeat 함수는 경우에 따라 변경되는 일을 함수 f로 추상화하고 , 이를 외부에서 전달받음

 

콜백 함수 (callback function)

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

- 함수형 패러다임, 비동기 처리에 활용되는 중요한 패턴 

 

고차 함수 (Higher-Order function)

- 매개변수를 통해 함수의 외부에서 콜백함수로 전달 받은 함수 

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

- 고차함수는 매개변수로 통해 전달받은 콜백 함수의 호출 시점을 결정해서 호출

 

 

12.6.5 순수 함수와 비순수 함수 

 

순수 함수 (pure function)

 

- 어떤 외부 상태에도 의존하지 않고 변경하지도 않는 함수 

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

- 함수의 외부상태를 변경하지 않음

var count = 0; //현재 카운트를 나타내는 상태 

//순수 함수 increase는 동일한 인수가 전달되면 언제나 동일한 값 반환
function increase(n) {
  return ++n;
}

//순수 함수가 반환한 결과값을 변수에 재할당해서 상태를 변경
count = increase(count);
console.log(count); //1

count = increase(count);
console.log(count); //2

 

비순수 함수 (impure function)

 

 - 외부상태에 의존하거나 외부 상태를 변경하는 함수 

 - 함수 내부에서 외부 상태를 직접 참조 

 - 매개변수를 통해 객체를 전달 받음

var count = 0; //현재 카운트를 나타내는 상태 : increase 함수에 의해 변화

//비순수 함수 
function increase() {
  return ++count; //외부 상태에 의존하며 외부 상태를 변경
}

//비순수 함수는 외부 상태 (count)를 변경하므로 상태 변화를 추적하기 어려워짐
increase();
console.log(count); //1

increase();
console.log(count); //2

 

함수형 프로그래밍

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