TIL01. JavaScript : Function 정리

44709 단어 JavaScriptJavaScript

🌈 Function 정리

🔥 Why : 함수를 왜 쓰나?

🔥 Return : 값만 찍는 함수와 값을 담는 함수

🔥 Parameter : 김밥 머신과 속재료

🔥 Copy Function : 김밥 머신을 복사하는 법과 김밥을 복사하는 법

🔥 Arrow Function


1. Why : 함수를 왜 쓰나?


🤔 행운의 편지를 보내봅시다:)

함수도 변수처럼 상자입니다. 하지만 함수는 어떠한 작동이나 처리 과정을 담을 수 있습니다. 물론 함수도 변수에 담을 수 있지만, 단지 어떤 내용을 담기만 하는 변수와는 다르게 함수는 그 자체로 어떠한 기능("기능을 못하는 것과 기능을 안하는 것은 차이가 있습니다.")을 갖고 있는 상자입니다. 일종의 작은 머신이죠! 친구에게 행운의 편지를 보내야한다고 생각해 봅시다. 단, 붙여넣기는 안되고, 편지의 시작과 끝에 친구의 이름을 적어줘야 합니다. 편지 내용을 작성하여 console.log로 찍어보겠습니다.

// 첫번째 편지 : 철수
console.log('철수야,,이 편지는 영국에서 최초로 시작되어 일년에 한 바퀴 돌면서 받는 사람에게 행운을 주었어. 지금은 너에게로 보내진 이 편지는 4일 안에 너의 곁을
떠나야 해. 이 편지를 포함해서 7통을 행운이 필요한 사람에게 보내 줘야해. 복사를 하면 절대 안되. 혹 미신이라 하실지 모르지만 정말 사실이야. 이 편지를 보내면 7년의 행운이
있을 것이고 그렇지 않으면 3년의 불행이 있을 거야. 그리고 이 편지를 버리거나 낙서를 해서는 큰일나. 7년의 행운을 빌면서.. 철수에게')
// 두번째 편지 : 영희
console.log('영희야,,이 편지는 영국에서 최초로 시작되어 일년에 한 바퀴 돌면서 받는 사람에게 행운을 주었어. 지금은 너에게로 보내진 이 편지는 4일 안에 너의 곁을
떠나야 해. 이 편지를 포함해서 7통을 행운이 필요한 사람에게 보내 줘야해. 복사를 하면 절대 안되. 혹 미신이라 하실지 모르지만 정말 사실이야. 이 편지를 보내면 7년의 행운이
있을 것이고 그렇지 않으면 3년의 불행이 있을 거야. 그리고 이 편지를 버리거나 낙서를 해서는 큰일나. 7년의 행운을 빌면서.. 영희에게')
// 세번째 편지 : 윤우
console.log('윤우야,,이 편지는 영국에서 최초로 시작되어 일년에 한 바퀴 돌면서 받는 사람에게 행운을 주었어. 지금은 너에게로 보내진 이 편지는 4일 안에 너의 곁을
떠나야 해. 이 편지를 포함해서 7통을 행운이 필요한 사람에게 보내 줘야해. 복사를 하면 절대 안되. 혹 미신이라 하실지 모르지만 정말 사실이야. 이 편지를 보내면 7년의 행운이
있을 것이고 그렇지 않으면 3년의 불행이 있을 거야. 그리고 이 편지를 버리거나 낙서를 해서는 큰일나. 7년의 행운을 빌면서.. 윤우에게')
// 네번째 편지 : 태희
console.log('태희야,,이 편지는 영국에서 최초로 시작되어 일년에 한 바퀴 돌면서 받는 사람에게 행운을 주었어. 지금은 너에게로 보내진 이 편지는 4일 안에 너의 곁을
떠나야 해. 이 편지를 포함해서 7통을 행운이 필요한 사람에게 보내 줘야해. 복사를 하면 절대 안되. 혹 미신이라 하실지 모르지만 정말 사실이야. 이 편지를 보내면 7년의 행운이
있을 것이고 그렇지 않으면 3년의 불행이 있을 거야. 그리고 이 편지를 버리거나 낙서를 해서는 큰일나. 7년의 행운을 빌면서.. 태희에게')
// 다섯번째 편지 : 유리
console.log('유리야,,이 편지는 영국에서 최초로 시작되어 일년에 한 바퀴 돌면서 받는 사람에게 행운을 주었어. 지금은 너에게로 보내진 이 편지는 4일 안에 너의 곁을
떠나야 해. 이 편지를 포함해서 7통을 행운이 필요한 사람에게 보내 줘야해. 복사를 하면 절대 안되. 혹 미신이라 하실지 모르지만 정말 사실이야. 이 편지를 보내면 7년의 행운이
있을 것이고 그렇지 않으면 3년의 불행이 있을 거야. 그리고 이 편지를 버리거나 낙서를 해서는 큰일나. 7년의 행운을 빌면서.. 유리에게')
// 여섯번째 편지 : 창희
console.log('창희야,,이 편지는 영국에서 최초로 시작되어 일년에 한 바퀴 돌면서 받는 사람에게 행운을 주었어. 지금은 너에게로 보내진 이 편지는 4일 안에 너의 곁을
떠나야 해. 이 편지를 포함해서 7통을 행운이 필요한 사람에게 보내 줘야해. 복사를 하면 절대 안되. 혹 미신이라 하실지 모르지만 정말 사실이야. 이 편지를 보내면 7년의 행운이
있을 것이고 그렇지 않으면 3년의 불행이 있을 거야. 그리고 이 편지를 버리거나 낙서를 해서는 큰일나. 7년의 행운을 빌면서.. 창희에게')
// 일곱번째 편지 : 혁수
console.log('혁수야,,이 편지는 영국에서 최초로 시작되어 일년에 한 바퀴 돌면서 받는 사람에게 행운을 주었어. 지금은 너에게로 보내진 이 편지는 4일 안에 너의 곁을
떠나야 해. 이 편지를 포함해서 7통을 행운이 필요한 사람에게 보내 줘야해. 복사를 하면 절대 안되. 혹 미신이라 하실지 모르지만 정말 사실이야. 이 편지를 보내면 7년의 행운이
있을 것이고 그렇지 않으면 3년의 불행이 있을 거야. 그리고 이 편지를 버리거나 낙서를 해서는 큰일나. 7년의 행운을 빌면서.. 혁수에게')

7개의 편지를 보냈을 뿐인데,, 엄청 긴 코드가 생겨버렸습니다. 친구의 이름이 들어가는 부분을 변수로 바꾼다해도 그 자리는 변수명이 차지하기 때문에 코드를 효과적으로 줄이는데 도움이 되지 않겠죠. 이처럼 중복되는게 많을 때는 첫번째 함수를 떠올려야합니다. 함수는 중복되는 부분을 효과적으로 줄여주고, 어디서든 재사용할 수 있습니다. 'sendToLetter'라는 이름으로 위와 같은 결과를 만들 수 있도록 함수를 작성해 보겠습니다.

function sendToLetter(name){
  let text = name+'야,, 이 편지는 영국에서 최초로 시작되어 일년에 한 바퀴 돌면서 받는 사람에게 행운을 주었어. 지금은 너에게로 보내진 이 편지는 4일 안에 너의 곁을
  떠나야 해. 이 편지를 포함해서 7통을 행운이 필요한 사람에게 보내 줘야해. 복사를 하면 절대 안되. 혹 미신이라 하실지 모르지만 정말 사실이야. 이 편지를 보내면 7년의 행운이
  있을 것이고 그렇지 않으면 3년의 불행이 있을 거야. 그리고 이 편지를 버리거나 낙서를 해서는 큰일나. 7년의 행운을 빌면서.. ' + name + '에게';
  console.log(text)
};
sendToLetter('철수')
sendToLetter('영희')
sendToLetter('윤우')
sendToLetter('태희')
sendToLetter('유리')
sendToLetter('창희')
sendToLetter('혁수')

✔️ 즉, 함수를 사용하는 이유는 첫번째 재사용성입니다. 정의한 함수를 호출만 함으로써 재사용할 수 있습니다.
✔️ 두번째는 가독성입니다. name값을 받아 맨 앞 부분과 맨 뒷부분에 합쳐주는 구조를 한 눈에 파악할 수 있습니다. 또한 'sendToLetter'라는 함수명을 통해 함수의 대략적인 기능에 대해 알아채기 쉽습니다.
✔️ 세번째는 모듈화입니다. 코드의 규모가 커질 수록 지금 작동하는 코드가 어디서부터 어디까지 작동하고, 영향을 주는지 파악하기 쉽지 않습니다. 함수를 사용하면, 함수의 기능별로 독립된 영역을 가지기 때문에 서로 영향을 미치지 않고 유지보수나 버그가 발생 시 어디서 발생했는지 파악하기 용이합니다.


🤔 함수는 어떻게 생겼을까?

함수는 기본 구조는 함수명, 인자, 처리 절차로 나뉩니다. 또는 함수 사용과 관련해서 함수 선언, 함수 호출로 나뉘기도 합니다.

  • 함수명은 말 그대로 함수의 이름입니다. 이 이름으로 함수를 어디서든 호출하여 작동시킬 수 있습니다. 아래 그림에서는 'addNumbers'가 함수명입니다.
  • 인자(parameter)는 함수 내에 무언가 주입시킬 때 사용하는 통로입니다. 인자가 없을 때도 있지만, 여러개 있을 때도 있고, 확정된 인자의 갯수가 없을 때도 있습니다. 아래 그림에서는 함수명 옆에 () 부분이 인자를 받는 함수의 입구입니다.
  • 입구 안에는 여러개의 통로가 있을 수 있는데, 인자들이 길을 헤메지 않도록 통로의 이름을 정해주어야 합니다. 입구 안에 이름이 달린 통로가 있다면 인자가 있는 것 입니다.
  • 처리(code)는 이 함수의 본질적인 기능을 담당하는 로직입니다. {}안에 정해진 기능에 따라 함수는 작동합니다. 아래 'addNumbers" 함수에서는 a,b를 인자로 전달받아 그 둘을 더하는 기능을하고 있습니다.
  • 위의 세가지 구조로 함수는 정의되고, 함수를 사용하기 위해서는 필요한 곳에 함수명을 호출함으로써 사용할 수 있습니다. 아이폰에서 시리아를 부르면 시리아가 대답하는 것처럼 함수명에 parameter를 전달할 수 있는 입구를 달아주면 함수를 실행됩니다. 만일 함수가 정의된 부분에 인자가 있다면, 인자값을 입력해주어야 합니다.

🤔 함수 선언문과 함수 표현식

함수선언문은 아래와 같이 생겼습니다. 지금까지 일반적으로 선언했던 함수가 함수선언문 방식을 따른 것입니다. 함수 선언문은 가장 기본적인 형태지만, 함수가 선언되지 전에도 호출할 수 있다는 특이점이 있습니다. 코드를 실행시키면, 코드는 위에서부터 아래로 읽혀져 내려가기 때문에 아직 선언되지 않은 함수를 호출하면 에러가 발생해야 하는데 그렇지 않고 정상적으로 작동합니다. 아마.. 함수를 별도로 보관해서 선언 위치와 관련없이 호출되면 바로 작동할 수 있게 하는 것 같습니다.

sayHello()
function sayHello(){
  console.log("안녕하세요! 만나서 반갑습니다")
}
sayHello()

함수표현식은 아래와 같이 생겼습니다. 함수명을 꺼내서 변수에 담고, 변수명을 호출하여 함수를 작동시키는 선언 방식입니다. 단, 함수표현식을 사용했을 때는 선언 뒤 함수를 호출하지 않으면 'ReferenceError'를 만나게 됩니다.

// sayHello() ReferenceError : Cannot access 'sayHello' before initialization
let sayHello = function(name){
  console.log("안녕하세요! 만나서 반갑습니다")
}
sayHello()


2. Return : 값만 찍는 함수와 값을 담는 함수

🤔 내 함수가 깡통이라고?

함수에 return을 매우 중요합니다. return의 기능을 알아봅시다. return은 2가지 대표적인 핵심 기능을 갖고 있습니다. 그 중 하나는 결과값 전달이라는 기능입니다.
결과값을 전달한다는 말은 처음 이해하기 어렵습니다. 함수 내에서 console.log()로 값을 출력해도 마치 그 함수가 값을 갖고 있다고 착각하기 쉽기 때문입니다. 'moneyCopyMechine' 함수는 돈을 10배로 복사하는 머신입니다. 인자로 넣어준 금액을 10배로 불려주죠. 함수를 실행시키면 콘솔에 만원이 10배가되어 100000이 출력됩니다. 하지만 이 값은 함수 내에서 console.log가 작동한 결과입니다. 호출된 함수의 값을 확인해보기 위해 myMoney에 담아 맨 아래에서 출력하였더니 undefined가 출력됩니다.
console.log는 코드를 작성하는 중 값을 잘 받아왔는지, 의도대로 처리되고 있는지 중간에 점검하기 위해 정말 중요한 도구입니다. 하지만 출력되었다고해서 그 함수가 값을 가지고 있다고 오해해서는 안됩니다. 아래 'moneyCopyMechine'는 마치 깡통함수와 같습니다. 처리하는 로직은 존재하지만 결국 남는게 없습니다. 아무 값도 갖고 있지 않기 떄문에 전재산을 날린 것과 같습니다.

function moneyCopyMechine(money){
  money = money * 10
  console.log(money) // 👈 콘솔에 100000은 여기서 출력된 결과일 뿐이에요:)
}
let myMoney = moneyCopyMechine(10000)
console.log(myMoney) // 👈 undefined

🤔 그래서,, return 이 뭔데?

return은 함수의 결과값을 전달합니다. 어디에 전달할까요? 호출한 함수가 깡통이 아닌, 결과물을 담고 있도록 호출한 곳에 값을 전달시킵니다. console.log가 아닌 return으로 money를 전달했더니 호출한 함수를 담은 'myMoney'에서 100000을 갖고 있는 것을 아래처럼 확인할 수 있습니다.

function moneyCopyMechine(money){
  money = money * 10
  return money
}
let myMoney = moneyCopyMechine(10000)
console.log(myMoney) // 👈 100000

🤔 함수에서 return을 만나면!

return을 만나면 함수를 종료됩니다. 이를 증명하기 위해 첫번째 return 뒤에 출력문 2개와 그 사이에 return을 두고 실행해보겠습니다. 결과는 100000이 출력된 것을 확인할 수 있습니다.
이처럼 함수 내에서 return을 만나면 함수의 작동은 그 위치에서 멈추고, 값을 반을 반환합니다. 첫번째로 만나는 return에서 종료되기 이후에 코드는 의미가 없습니다.

function moneyCopyMechine(money){
  money = money * 10
  return money
  console.log('1. 이곳이 출력된다면,, 첫번째 return 후 함수가 작동한거에요.') // 👈 작동되지 않습니다.
  return money / 2 // 👈 작동되지 않습니다.
  console.log('2. 이곳이 출력된다면,, 두번째 return 후에도 함수가 작동한거에요.') // 👈 작동되지 않습니다.
}
let myMoney = moneyCopyMechine(10000)
console.log(myMoney)  // 👈 100000


3. Parameter : 김밥 머신과 속재료


🤔 parameter1. 김밥 함수를 만들어보쟈!

위에서 정리한것 처럼 인자(parameter)는 함수로 전달되는 값입니다. 전달할 값은 함수를 호출할 때, 함수의 입구인 () 안에 배치시켜, 함수와 내에서 작동할 수 있도록 합니다. 아래는 김밥을 만드는 머신입니다. 참치를 넣으면 참치김밥, 치즈를 넣으면 치즈김밥, 스팸을 넣으면 스팸 김밥입니다.

function makeKimbab(ingredient){
  console.log('김밥 김을 하나 꺼냅니다.')
  console.log('고슬고슬한 밥을 김 위에 올려 폅니다.')
  console.log(ingredient+',', '단무지,', '맛살,','시금치를 올립니다.')
  console.log('김밥을 균일하게 썰어 포장합니다.')
  let kimbab = ingredient + 'Kimbap';
  return kimbab
}
// order1
let order1 = makeKimbab('Tuna')
console.log(order1+'이 완성되었습니다.') // TunaKimbap이 완성되었습니다.
// order2
let order2 = makeKimbab('Cheese')
console.log(order2+'이 완성되었습니다.') // CheeseKimbap이 완성되었습니다.
// order3
let order3 = makeKimbab('Spam')
console.log(order3+'이 완성되었습니다.') // SpamKimbap이 완성되었습니다.

🤔 parameter2. 누가 시킨건데??

때로는 parameter를 여러개 받아 함수 기능 내에서 상호작용할 수 있도록 처리할 필요가 있습니다. 위에서 처럼 3개의 주문이아니라 주문이 5개가 들어왔는데, 중복되는 김밥이 있으면 누구의 김밥인지 파악하기 어렵겠죠. 이럴 때 parameter를 한개 더 받아 누군지 확인할 수 있습니다.
이처럼 parameter는 필요에 따라 여러개를 사용할 수 있습니다. 아래 코드를 확인해볼께요:)

function makeKimbab(who, ingredient){
  console.log('김밥 김을 하나 꺼냅니다.')
  console.log('고슬고슬한 밥을 김 위에 올려 폅니다.')
  console.log(ingredient+',', '단무지,', '맛살,','시금치를 올립니다.')
  console.log('김밥을 균일하게 썰어 포장합니다.')
  let kimbab = who + '님이 주문한 ' + ingredient + 'Kimbap이 완성되었습니다.';
  return kimbab
}
// order1
let order1 = makeKimbab('재원', 'Tuna')
console.log(order1) // 재원님이 주문한 TunaKimbap이 완성되었습니다.
// order2
let order2 = makeKimbab('혜진', 'Cheese')
console.log(order2) // 혜진님이 주문한 CheeseKimbap이 완성되었습니다.
// order3
let order3 = makeKimbab('보람', 'Cheese')
console.log(order3) // 보람님이 주문한 CheeseKimbap이 완성되었습니다.
// order4
let order4 = makeKimbab('민준', 'Spam')
console.log(order4) // 민준님이 주문한 SpamKimbap이 완성되었습니다.

🤔 parameter3. 기본 김밥도 필요할 때!

선언한 함수에 parameter가 있는데 불구하고, 함수 호출 부분에서 parameter를 전달하지 않는다면 에러가 발생합니다. 만일 함수에 parameter가 전달되지 않는다면 미리 정해둔 default값이 parameter로 작동될 수 있게하면 어떨까요? parameter의 default로 'basic'을 지정해두겠습니다.

function makeKimbab(who, ingredient='Basic'){
  console.log('김밥 김을 하나 꺼냅니다.')
  console.log('고슬고슬한 밥을 김 위에 올려 폅니다.')
  console.log(ingredient+',', '단무지,', '맛살,','시금치를 올립니다.')
  console.log('김밥을 균일하게 썰어 포장합니다.')
  let kimbab = who + '님이 주문한 ' + ingredient + 'Kimbap이 완성되었습니다.';
  return kimbab
}
// order1
let order1 = makeKimbab('재원')
console.log(order1) // 재원님이 주문한 BasicKimbap이 완성되었습니다.
// order2
let order2 = makeKimbab('혜진', 'Tuna')
console.log(order2) // 혜진님이 주문한 CheeseKimbap이 완성되었습니다.
// order3
let order3 = makeKimbab('보람', 'Cheese')
console.log(order3) // 보람님이 주문한 CheeseKimbap이 완성되었습니다.
// order4
let order4 = makeKimbab('민준')
console.log(order4) // 민준님이 주문한 BasicKimbap이 완성되었습니다.

🤔 parameter4. 내맘대로 김밥!

parameter로 2개가 전달될수 있고, 3개가 전달될 수도 있고, 10개가 전달될 수도 있게 하고 싶어요. 마치 원하는 속재료를 다 넣어 나만의 김밥을 만드는것 처럼요! 그럴땐 ...을 parameter에 붙입니다. 마치 python에서 *args로 여러개의 파라미터를 다 받을 수 있는 것 처럼 말이죠.

function makeKimbab(who, ...ingredient){
  console.log('김밥 김을 하나 꺼냅니다.')
  console.log('고슬고슬한 밥을 김 위에 올려 폅니다.')
  console.log(ingredient+',', '단무지,', '맛살,','시금치를 올립니다.')
  console.log('김밥을 균일하게 썰어 포장합니다.')
  let kimbab = who + '님이 주문한 ' + ingredient + 'Kimbap이 완성되었습니다.';
  return kimbab
}
// order1
let order1 = makeKimbab('재원')
console.log(order1) // 재원님이 주문한 BasicKimbap이 완성되었습니다.
// order2
let order2 = makeKimbab('혜진', 'Tuna', 'Kimchi', 'Spam', 'Cheese')
console.log(order2) // 혜진님이 주문한 Tuna,Kimchi,Spam,CheeseKimbap이 완성되었습니다.
// order3
let order3 = makeKimbab('보람', 'Pig', 'Kimchi', 'Anchovy')
console.log(order3) // 보람님이 주문한 Pig,Kimchi,AnchovyKimbap이 완성되었습니다.


4. Copy Function : 김밥 머신을 복사하는 법과 김밥을 복사하는 법


🤔 함수 복사할 때 주의할 점.

함수의 복사는 아래처럼 새로운 변수에 넣어주면 또 다른 이름으로 같은 기능의 함수를 사용할 수 있어요. 주의할 점은 ()를 붙이면 안됩니다. ()를 붙인다는건 함수의 호출한 것이기 때문에 호출된 결과값이 새로운 변수에 담기기 때문입니다.

// 함수 복사
function makeKimbab(who, ingredient){
  let kimbab = `${who}님이 주문한 ${ingredient} Kimbap이 완성되었습니다.`
  return kimbab
}
makeKimbab2 = makeKimbab
console.log(makeKimbab2('재원', 'Tuna'))
console.log(makeKimbab('혜진', 'Spam'))

함수를 호출한 결과를 함수처럼 사용하면, 아래처럼 TypeError이 발생합니다.

// 함수결과 복사
function makeKimbab(who, ingredient){
  let kimbab = `${who}님이 주문한 ${ingredient} Kimbap이 완성되었습니다.`
  return kimbab
}
makeKimbab2 = makeKimbab()
console.log(makeKimbab2('재원', 'Tuna')) // TypeError: makeKimbab2 is not a function

즉, 함수를 복사한다는 의미는 같은 기능을 다른 함수로 이용하고 싶을 때, 사용합니다. 마치 김밥 머신을 하나 더 만드는 것과 같습니다. 이와 반대로 함수가 호출되어 반환한 결과는 함수처럼 사용할 수 없을 뿐만아니라, 값을 갖고 있는 변수일 뿐입니다.



5. Arrow Function


🤔 Arrow Function 사용법

화살표 함수(Arrow Function)는 ES6에 추가된 문법으로 함수 표현식을 더욱 간결하게 만들어 줍니다. 화살표 함수는 익명함수로 아래와 같은 규칙으로 함수표현식을 축약하여 표현할 수 있습니다. 익숙해지는데 시간을 걸리지만, 이런 코드를 사용해야할 때가 있기 때문에 눈에 익혀둡시다:)
기본 형태 🔍 let 함수이름 = (parameter1, parameter2..) => {Function Body}

  • 함수에 전달할 parameter가 1개 뿐이면 ()로 생략 가능
  • body가 1줄이라면, 스코프({}) 뿐아니라 return도 생략 가능
  • body가 2줄 이상이라면, {}를 명시해주고, 값을 전달하기 위해 return 입력
// 기본 함수 표현식(익명 함수)
const add = function (a, b) {
  return a + b;
};
// 화살표 함수(1단 body)
const add = (a, b) => a + b; // 👈 body가 1줄일 때는, {} 및 return 까지 생략 가능
// 화살표 함수(2단 이상 body)
const add = (a, b) => {
  let result = a + b;
  return result; // 👈 스코프를 사용했다면, return으로 결과값을 반환 필수
};

좋은 웹페이지 즐겨찾기