[JavaScript] 루프 함수 만들기

비얌·2023년 1월 9일
2
post-thumbnail

개요

어떤 함수를 완성하는 자바스크립트 과제를 받았다! 함수 호출에 필요한 인수와 그 함수를 호출한 결과를 보고 함수의 본문을 예상하여 만드는 과제였다.



문제 설명

looper라는 함수를 완성해야 한다. looper 함수를 호출할 때, 아래처럼 몇 개의 인자를 전달한다. 그러면 첫 번째 예시에서는 0부터 9까지, 두 번째 예시에서는 'ㅋ'이 20번 출력된다.

// 0 1 2 3 4 5 6 7 8 9
looper(
  0,
  (val) => val < 10,
  (val) => {
    console.log(val);
    return val + 1
  }
);

// ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
looper(
  "ㅋ",
  (val) => val.length < 20,
  (val) => val + "ㅋ",
  (val) => console.log(val)
);

looper라는 함수에 가보면 initial, condition, task, fin 이렇게 네 개의 인수가 있다. 이 함수의 본문을 채우는 것이 과제이다.

function looper(initial, condition, task, fin) {
  
}

각 인수에 대한 설명은 아래와 같다.

/**
 * 초기값으로 시작해서, 지정한 조건이 참인 동안 작업을 실행하고,
 * 조건이 거짓이 되면 마무리 작업을 실행하는 함수
 *
 * @param initial 내부 변수의 초기값
 * @param condition 내부 변수를 입력으로 받아, 반복을 계속할지 말지를 반환하는 함수
 * @param task 내부 변수를 입력으로 받아, 작업을 실행한 후 결과를 반환하는 함수. 실행 결과는 내부 변수에 다시 대입되어야 함
 * @param fin 반복이 끝났을 때 내부 변수를 입력으로 받아 실행되는 동작, undefined일 수 있음
*/


완성된 코드

풀이 과정에서는 삽질한 과정도 다룰 것이기 때문에 풀이 과정에 앞서 완성된 코드를 먼저 올리려고 한다.

// index.js
function looper(initial, condition, task, fin) {
  let result = initial;
  while (condition(result)) {
    result = task(result);
  }
  if (fin) {
    fin(result);
  }
}


풀이 과정

함수 표현식, 화살표 함수

일단 문제를 해석하는 과정에서 문제가 생겼다. 사실 나는... 화살표 함수가 헷갈린다😂 그래서 화살표 함수를 찾아보려다가, 그 전에 함수 표현식부터 공부해보기로 했다.


함수 표현식은 모던 자바스크립트 튜토리얼의 함수 표현식 챕터에서 공부했다.

자바스크립트는 함수를 특별한 종류의 값으로 취급한다고 한다. 그래서 우리가 보통 아는 함수 선언식을 함수 표현식으로 표현할 수 있다.

// 함수 선언식
function sayHi() {
  console.log( "Hello" );
}
// 함수 표현식
let sayHi = function() {
  console.log( "Hello" );
};

이를 화살표 함수로 표현하면 아래와 같다. 이 부분은 함수 표현식 챕터에서 공부했다.

// 화살표 함수
let sayHi = () => console.log("Hello");

condition

함수 표현식, 화살표 함수 등을 공부한 이유는 바로 looper의 인수로 들어가는 condition을 이해하기 위해서였다.

condition인 (val) => val < 10가 이해가지 않았다.

// 0 1 2 3 4 5 6 7 8 9
looper(
  0,
  (val) => val < 10,
  (val) => {
    console.log(val);
    return val + 1; // 돌 때마다 실행
  }
);

이때 얼마전에 배운 '자바스크립트에서 표현식은 값을 반환한다'는 개념을 떠올렸다. 여기서 (val) => val < 10는 표현식이고, 따라서 어떤 값을 반환하여 looper 함수의 인수로 들어갈 것이다.

그래서 아래처럼 함수 표현식으로 화살표 함수를 나타내보기로 했다.

let result = (val) => val < 10;

그리고 result를 console.log로 출력해봤다. result에는 인자로 1을 넣어봤다.

console.log(result(1));

그랬더니..!! 예상치 못한 결과가 나왔다. 바로, true 라는 결과가 나온 것이다. 불리언이 나올 거라고는 예상하지 못했다. 화살표 함수와 조건식에 대한 개념이 부족해서 그랬던 것 같다. 결과를 확인한 후, looper의 인자인 condition을 이해하게 되었다.

looper 함수가 인수로 들어오는 condition을 만족(true)할 때까지만 루프를 돌게 만들어야 할 것이다.


while

while이나 for문을 사용해서 루프를 돌아야 할 것 같아서 이들을 공부하게 되었다. while은 언제 봐도 헷갈려서, 모던 자바스크립트 튜토리얼의 while과 for 반복문 챕터를 공부했다.


아래는 while문의 문법이다. condition(조건)이 truthy 이면 반복문 본문의 코드가 실행된다. 따라서 만약 condition이 i < 3이라면 i < 3을 만족할 동안 while문을 돌게 된다.

while (condition) {
  // 코드
  // '반복문 본문(body)'이라 불림
}

💥 문제가 있다!

하지만, 문서에서 배운 condition은 val < 10와 같은 형태인데 반해 looper의 인자로 들어가는 condition은 (val) => val < 10와 같은 형태였다. 그래서 어떻게 해야할지 많은 고민이 되었다.

조건문은 무조건 truthy 혹은 falsy라는 값을 반환해야 하는데, (val) => val < 10와 같은 표현식은 말 그대로 표현식이었기 때문이다. 하지만, 자바스크립트에서 표현식은 값을 반환한다는 것을 떠올렸다. condition(val)와 같이 하면 truthy 혹은 falsy한 값을 반환할 것이다.


looper 함수 본문 작성하기

일단 초기값인 initial이 task의 본문에 따라 변화하다가, condition이 falsy가 되면 멈추고 fin이 있다면 fin을 실행한 후 끝나면 되는 것 같다고 분석했다.

처음에는 아래와 같이 작성했었다. 하지만 이렇게 하니까 0만 무한으로 출력되는 오류가 발생했다. 그래서 대체 어디가 틀린 것일까 고민했다.

function looper(initial, condition, task, fin) {
  let result = initial;
  while (condition(result)) {
    result = task(initial);
  }
}

확인 결과, result = task(initial); 이 부분이 잘못된 것을 발견했다. task에 변하지 않는 초깃값인 initial이 계속 들어가니 result도 계속 같은 값이 될 수밖에 없고 10보다 작다는 조건을 만족하여 무한으로 같은 값이 출력되는 것이었다. 이 부분의 initial을 result로 변경해야 한다.

function looper(initial, condition, task, fin) {
  let result = initial;
  while (condition(result)) {
    result = task(result);
  }
}

그리고 마지막으로, fin이라는 인자가 있으면 내부 변수를 입력으로 받아 fin을 실행해야 한다. 이는 마지막에 if (fin) {fin(result)}를 추가하여 해결할 수 있다.


이렇게 하면, 최종 코드는 아래와 같이 된다!

// index.js
function looper(initial, condition, task, fin) {
  let result = initial;
  while (condition(result)) {
    result = task(result);
  }
  if (fin) {
    fin(result);
  }
}


결과

의도했던 값을 출력하는데 성공했다 😆



다른 풀이(숏코딩)

숏코딩으로도 작성할 수 있다는 것을 알게되었다.

재귀와 삼항연산자, 그리고 옵셔널 체이닝을 사용하면 아래와 같이 짧은 코드를 작성할 수 있다.

// index.js
function looper(initial, condition, task, fin) {
  condition(initial)
    ? looper(task(initial), condition, task, fin)
    : fin?.(initial);
}


🐹 회고

자바스크립트 과제를 하면서, 많이 알아가는 것 같다.

특히 이번 과제 덕분에 모호했던 함수 표현식과 화살표함수, while문에 대한 개념을 더 확실하게 알아갈 수 있었다.

분명히 모던 자바스크립트 튜토리얼로 함수 표현식과 화살표 함수에 대해 공부했고 정리도 했지만, 지금처럼 와닿지는 않았다. 실제로 그 개념이 필요한 상황이 아니었기 때문에 공부를 했어도 기억에 남지 않았던 것 같다.

그리고 while문은 분명히 언어를 배우는 초기에 배웠던 개념인 것 같은데, 항상 처음 배우는 것 같이 느껴진다. 초기에 배운다고 해서 쉽거나 중요하지 않은 개념이 아니라는 것을 다시 한번 알게 되었다.

개념을 배우는 것도 무척 중요하지만, 이렇게 뭔가 만들고 풀어보면서 공부하는 것도 정말 중요하고 많은 도움이 되는 것 같다!! 😊

profile
🐹강화하고 싶은 기억을 기록하고 공유하자🐹

0개의 댓글