함수

@choi2021 · September 13, 2022 · 8 min read

시작하기 앞서

매일 TIL로 짤막하게 공부한 내용을 정리하려 했지만 하나의 주제의 맥락을 다 담기 힘든 부분이 있어서 작은 주제 하나씩 정하고 글을 써나가 보려 한다.

1) 함수의 정의

함수는 어떠한 하나의 일을 수행할 수 있는 관련 코드들의 모음이라고 할 수 있다. 함수를 잘 작성하면 관련 코드가 한 곳에 모여있기에 유지보수에 유리하고. 필요할 때마다 재 사용할 수 있으며, 가독성이 높은 장점을 갖는다. 함수는 다음과 같은 구조를 갖는다.

function multiply(a, b) {
  return a * b
}

위 코드는 multiply라는 이름을 가진 함수를 선언하는 선언문이다. function이라는 키워드로 선언문을 시작하며 함수의 이름과 함수의 인자들을 순서대로 작성한다. 코드 블럭 안에는 일처리를 위한 코드들을 담고 반환할 값은 return을 통해 전달한다.

이러한 함수는 자바스크립트에서 오브젝트 데이터 타입을 가지고 있어 힙에 저장되며, 호이스팅을 통해 코드의 가장 위로 올라가 선언되어 코드 순서와 상관없이 사용이 가능하다. (Hoisting은 중요한 주제이기 때문에 나중에 자세히 다루려 한다)

함수는 오브젝트이기 때문에 갖는 또 다른 특징이 있는데 "값을 갖는다"는 점이다. 이러한 특징을 이용해 자바스크립트에서 만드는 방법에는 두 가지가 존재한다. 함수 선언문함수 표현식이다.

2) 함수 선언문과 함수 표현식

함수 선언문은 이미 설명한 구조로 이루어져 있으며, 함수 표현식은 다음과 같이 정의할 수 있다.

//함수 표현식의 첫번재 방법
let multiply = function (a, b) {
  return a * b
}

//함수 표현식의 두번째 방법:arrow function
mulitiply = (a, b) => {
  return a * b
}

multiply = (a, b) => a * b

함수는 오브젝트이기 때문에 함수를 가리키고 있는 주소 값을 가진다. 이 주소 값을 변수에 할당한 문이 "함수표현식"이며 구조는 할당하는 부분을 제외하고 선언문과 유사하다. 함수 표현식에는 위와 같은 방법 외에 화살표 함수 (arrow function)으로도 나타낼 수 있다. 화살표 함수는 함수 표현식보다 간략하게 표현할 수 있는 방법으로 인자를 먼저 작성한 후 =>와 함께 코드블럭을 작성한다. 이때 코드블럭 내 특정한 일을 하지 않고 반환 값만 존재한다면 생략하고 반환할 값만 작성할 수도 있다.

3) 함수의 인자

함수의 인자는 함수에 전달되는 요소들로 함수의 코드 블럭 내부 실행 컨텍스트 (자세한 부분은 클로저 부분에서 다시 설명하려 한다)에 등록된 변수라고 할 수 있다. 이러한 인자는 함수 내 오브젝트인 arguments로 전달된다.

function multiply(a, b) {
  console.log(arguments) //[1,2]
  return a * b
}
mulitply(1, 2)

다음과 같이 전달된 인자들은 arguments 배열에 각 요소로 저장되어 있으며, 얼마나 많은 인자들이 들어올지 모를 때는 다음과 같이 Rest parameters 을 사용할 수 있다.

function showRestParams(a, b, ...numbers) {
  console.log(arguments) //[1,2,3,4]
  console.log(numbers) //[3,4]
}
mulitply(1, 2, 3, 4)

4) 콜백함수 (Callback function)

콜백함수는 자바스크립트를 공부하고 프로젝트를 진행하면서 너무나도 중요하다고 많이 느낀 부분이라 꼭 정리가 필요했던 부분이었다. 앞서 함수는 오브젝트이기 때문에 참조 값, 주소 값을 저장하고 있다고 했다. 이때 콜백 함수는 말 그대로 필요한 때에 "call-back", 참조 값을 이용해 다시 호출되는 함수이다.

콜백함수가 가능한 이유는 자바스크립트가 일급함수 (1st-class function)를 가지고 있기 때문이다. 일급함수는 다음과 같이 정의될 수 있다.

  1. 다른 함수의 인자로 전달이 가능하다
  2. 함수가 다른 함수를 반환할 수 있다
  3. 변수에 할당할 수 있다
  4. 함수끼리 비교할 수 있다

위와 같은 특징은 모두 함수가 오브젝트이고 오브젝트는 주소값을 변수에 저장하기 때문에 가능하다. 그렇기에 콜백함수는 다른 함수의 인자로 전달되어 반환되어 필요한 때에 사용 가능하다. 이때 함수를 인자로 받고 반환하는 함수는 고차함수라고 한다. 예로 브라우저 API인 setTImeOut과 같은 함수가 될 수 있다.

setTimeout(() => {
  console.log(Date.now())
}, 1000)

setTimeOut은 정해진 시간 후에 전달 받은 함수를 실행하는 브라우저 API로 고차함수, 전달된 함수를 콜백함수 (일급함수) 라 할 수 있다.

5) 불변성

함수를 사용해서 값을 바꾸고 할 때, 주의할 점 중 하나인 불변성(immutability )에 대해 정리해 보고자 한다.

먼저 받은 인자가 원시형 타입의 값일 경우이다.

function changeToRedColor(a) {
  a = "Red"
  return a
}
const prevColor = "blue"
changeToRedColor(prevColor) //반환은 "Red"이지만 prevColor는 "blue"

원시형의 경우에는 전달 받은 인자의 값을 변경하더라도 블럭 외부의 변수에 영향을 끼치지 않는다. 문제는 전달한 인자가 오브젝트일 때 생긴다.

function changeToRedColor(a) {
  a.color = "Red"
}
const prevColor = { color: "blue" }
changeToRedColor(color)
console.log(a) //{color:"Red"}

위는 반환도 하지 않았지만 오브젝트 속성값이 바뀌어 버렸다. 이처럼 함수 내부에서 받은 인자를 바꾸는 코드는 예상하지 못할 에러를 만들 수 있으므로, 꼭 인자의 값을 수정해서 사용해야 한다면 이를 해결하기 위해 {...obj}와 같이 새롭게 오브젝트를 만드는 방법을 통해 사용해야 한다.

@choi2021
매일의 시행착오를 기록하는 개발일지입니다.