윤시의 블로그

[JavaScript] (함수, 함수 표현식, 화살표 함수 기본) 본문

JavaScript

[JavaScript] (함수, 함수 표현식, 화살표 함수 기본)

yo09 2024. 11. 29. 14:50

 

💡함수란?

  • 코드를 작성하다보면, 유사한 동작(기능)을 하는 코드가 여러 곳에서 필요할 때가 있음.
  • EX) 로그인 & 로그아웃 시 나타나는 안내 메시지
  • 함수는 불필요한 중복 없이 유사한 동작을 여러 번 호출할 수 있게 함.
  • 함수의 주요 용도 ⇒ 중복 코드 피하기

💡함수 선언

function showMessage() {
  alert( '안녕하세요!' );
}
  • 함수 선언 방식

→ funtion 함수명 ( 매개 변수 ) { 동작 내용 }

function 함수명(매개변수) {
  // 동작 내용
}
  • function 키워드로 함수 선언을 시작
  • 함수명은 함수의 이름이며, 이를 통해 함수를 호출할 수 있음
  • 괄호 () 안에는 매개변수를 넣습니다. 매개변수가 여러 개일 경우, 각 매개변수를 콤마로 구분함
  • 함수 본문은 {} 중괄호로 감싸서, 함수가 수행할 동작을 정의함
function showMessage() {
  alert( '안녕하세요!' );
}

showMessage();
showMessage();
  • **showMessage()**로 함수를 호출
  • 위 예시에서는 showMessage()를 2번 호출했으므로, alert창이 2번 뜸

💡지역 변수

  • 함수 내에서 선언한 변수를 지역 변수라 함.
  • 지역 변수는 함수 내부에서만 접근 가능하며, 함수 외부에서는 사용할 수 없음.
function showMessage() {
  let message = "안녕하세요!"; // 지역 변수

  alert( message );
}

showMessage(); // 안녕하세요!

alert( message ); 
// ReferenceError: message is not defined 
// (message는 함수 내 지역 변수이기 때문에 에러가 발생)

💡외부 변수

  • 함수 외부에서 선언한 변수를 외부 변수(또는 전역 변수)라고 함.
  • 외부 변수는 함수 안팎 어디에서나 접근 가능하며, 프로그램 전체에서 사용할 수 있음.
  • 접근 뿐만 아니라 수정도 할 수 있음.
let userName = 'John'; // username 변수 선언

function showMessage() {
  let message = 'Hello, ' + userName;
  alert(message);
}

showMessage(); // Hello, John

💡외부 변수와 지역 변수

  • 함수 내부에서 외부 변수를 수정할 때는 함수 밖에서 선언된 변수를 수정할 수 있음.
  • 하지만 함수 내부에 지역 변수가 동일한 이름으로 선언되면, 지역 변수외부 변수를 가리게 되어 외부 변수의 값은 수정되지 않음.
let userName = 'John';

function showMessage() {
  userName = "Bob"; // (1) 외부 변수를 수정함

  let userName = "Alice"; // (2) 지역 변수를 선언 (외부 변수를 가림)
  let message = 'Hello, ' + userName; // 지역 변수 userName 사용
  alert(message); // "Hello, Alice"
}

alert(userName); // 함수 호출 전이므로 "John"이 출력됨

showMessage(); // "Hello, Alice"가 출력됨

alert(userName); // 함수에 의해 외부 변수 userName은 수정되어 "Bob"이 출력됨

핵심 포인트

  • 외부 변수(userName)는 함수 외부에서 선언되어 있으며, 함수 안에서 수정 가능함.
  • 지역 변수(let userName inside showMessage)가 함수 내에서 선언되면, 외부 변수와 동일한 이름이라도 지역 변수가 외부 변수를 가림. 그로 인해 함수 내에서 userName이 "Alice"로 출력.
  • 그러나 외부 변수지역 변수가 없을 경우에만 수정됨. showMessage 함수 내부에서 지역 변수가 선언되지 않으면 외부 변수 userName이 "Bob"으로 바뀌게 됨.

💡매개 변수

  • 매개 변수를 이용하면, 임의 데이터를 함수 안에 전달할 수 있음.
  • 매개변수는 인자 OR 파라미터라고도 불림
function showMessage(from, text) { // 인자: from, text
  alert(from + ': ' + text);
}

showMessage('Ann', 'Hello!'); // Ann: Hello! (*)
showMessage('Ann', "What's up?"); // Ann: What's up? (**)

위 코드에서 showMessage 함수는 from, text라는 매개변수를 가짐.

function showMessage(from, text) {

  from = '*' + from + '*';

  alert( from + ': ' + text );
}

let from = "Ann";

showMessage(from, "Hello"); // *Ann*: Hello

// 함수는 복사된 값을 사용하기 때문에 바깥의 "from"은 값이 변경되지 않습니다.
alert( from ); // Ann
  • showMessage 함수는 두 개의 매개변수 from과 text를 받음.
  • 함수 내부에서 from의 값을 from으로 바꾸고, from과 text를 연결하여 alert을 띄움.
  • from이라는 변수를 "Ann"으로 선언.
  • showMessage(from, "Hello")을 호출할 때, from 변수의 값 "Ann"이 함수의 첫 번째 매개변수 from에 전달.
  • 함수 내부에서 from = '*' + from + '*'가 실행되면, from은 "*Ann*"로 변경.
  • 그래서 alert(from + ': ' + text)는 "*Ann*: Hello"를 출력.

중요 포인트

  • 함수 내에서 매개변수 from을 변경해도, 바깥의 from 변수는 변하지 않는다는 점!
  • 함수 showMessage에서 매개변수 from은 복사된 값으로 함수에 전달됨. 즉, 함수 내부의 from은 함수 외부의 from과는 별개임.
  • 함수 내에서 from을 "*Ann*"으로 바꿨지만, 바깥의 from은 여전히 "Ann"으로 유지됨.

 

💡기본값

  • 함수 호출 시 매개변수에 인수를 전달하지 않으면 그 값은 ⇒ undefined
function showMessage(from, text = "no text given") {
  alert( from + ": " + text );
}

showMessage("Ann"); // Ann: no text given

⇒ text가 값을 전달받지 못해도 undefined 대신 기본값 “no text given”이 할당됨.

function showMessage(from, text = anotherFunction()) {
  // anotherFunction()은 text값이 없을 때만 호출됨
  // anotherFunction()의 반환 값이 text의 값이 됨
}
  • 매개변수 기본값을 설정하는 방법 1
function showMessage(text) {
  // ...

  if (text === undefined) { // 매개변수가 생략되었다면
    text = '빈 문자열';
  }

  alert(text);
}

showMessage(); // 빈 문자열
  • 매개변수 기본값을 설정하는 방법 2

(if 문 대신 논리연산자 || 를 사용할 수 있음)

// 매개변수가 생략되었거나 빈 문자열("")이 넘어오면 변수에 '빈 문자열'이 할당됨
function showMessage(text) {
  text = text || '빈 문자열';
  ...
}
  • nullish 병합 연산자 사용
// 매개변수 'count'가 `undefined` 또는 `null`이면 'unknown'을 출력해주는 함수
function showCount(count) {
  alert(count ?? "unknown");
}

showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown

 

💡반환값

  • 함수를 호출했을 때 호출한 곳에 특정 값을 반환
function sum(a, b) {
  return a + b;
}

let result = sum(1, 2);
alert( result ); // 3

⇒ return은 함수 내 어디서든 사용 가능

⇒ return을 만나면, 함수 실행은 즉시 중단되고, 함수를 호출한 곳에 값을 반환.

 

  • 함수 하나에 여러 개의 return 문이 오는 경우
function checkAge(age) {
  if (age >= 18) {
    return true;
  } else {
    return confirm('보호자의 동의를 받으셨나요?');
  }
}

let age = prompt('나이를 알려주세요', 18);

if ( checkAge(age) ) {
  alert( '접속 허용' );
} else {
  alert( '접속 차단' );
}

⇒ 함수 하나에 여러 개의 return문이 올 수도 있음.

 

  • return만 명시하는 경우
function showMovie(age) {
  if ( !checkAge(age) ) {
    return;
  }

  alert( "영화 상영" ); // (*)
  // ...
}

⇒ return만 명시하는 경우, 함수가 즉시 종료됨.

 

※ 주의 ※

“return 값 사이에 절대 줄을 삽입하지 말 것!”

표현식을 여러 줄에 걸쳐 작성하고 싶다면 표현식이 return 지시자가 있는 줄에서 시작하도록 작성해야 함. 또는 아래와 같이 여는 괄호를 return 지시자와 같은 줄에 써줘도 괜찮음!

return (
  some + long + expression
  + or +
  whatever * f(a) + f(b)
  )

 

💡함수 이름짓기

  • 함수는 어떤 동작을 수행하기 위한 코드를 모아놓은 것!
  • 함수 이름은 가능한 간결, 명확해야 함.
  • 함수는 동작 하나만 담당해야 함!

⇒ 함수 이름에 언급되어 있는 동작만 수행! (그 외의 동작 수행X)

showMessage(..)     // 메시지를 보여줌
getAge(..)          // 나이를 나타내는 값을 얻고 그 값을 반환함
calcSum(..)         // 합계를 계산하고 그 결과를 반환함
createForm(..)      // form을 생성하고 만들어진 form을 반환함
checkPermission(..) // 승인 여부를 확인하고 true나 false를 반환함

 

  • 아래 3 코드는 모두 같은 동작을 함!
// if문 사용
function checkAge(age) {
  if (age > 18) {
    return true;
  } else {
    return confirm('보호자의 동의를 받으셨나요?');
  }
}
// 물음표 연산자 ? 사용
function checkAge(age) {
  return (age > 18) ? true : confirm('보호자의 동의를 받으셨나요?');
}
// OR 연산자인 '||' 사용
function checkAge(age) {
  return (age > 18) || confirm('보호자의 동의를 받으셨나요?');
}

 

💡함수 표현식

function sayHi() {   // (1) 함수 생성
  alert( "Hello" );
}

let func = sayHi;    // (2) 함수 복사

func(); // Hello     // (3) 복사한 함수를 실행(정상적으로 실행됩니다)!
sayHi(); // Hello    //     본래 함수도 정상적으로 실행됩니다.

 

💡콜백 함수

  • 예제) 매개변수가 3개 있는 함수, ask(question, yes, no)
function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

function showOk() {
  alert( "동의하셨습니다." );
}

function showCancel() {
  alert( "취소 버튼을 누르셨습니다." );
}

// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);

코드 분석

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

  • 이 함수는 세 개의 매개변수를 받음.
    1. question: 확인창에 표시될 질문 텍스트 (문자열).
    2. yes: 사용자가 확인 버튼을 눌렀을 때 실행할 함수 (콜백 함수).
    3. no: 사용자가 취소 버튼을 눌렀을 때 실행할 함수 (콜백 함수).
  • 함수 내부 로직:
    • confirm(question): 브라우저에서 확인/취소를 묻는 팝업 창을 띄움.
      • 사용자가 확인 버튼을 누르면 true를 반환하고, 취소 버튼을 누르면 false를 반환함.
    • if (confirm(question)) yes():
      • 팝업에서 확인을 선택하면 yes() 콜백 함수가 실행
    • else no():
      • 팝업에서 취소를 선택하면 no() 콜백 함수가 실행
ask("동의하십니까?", showOk, showCancel);
  • ask 함수는 질문과 두 개의 콜백 함수(showOk와 showCancel)를 인수로 받음
  • 실행 과정
    1. 사용자에게 confirm("동의하십니까?") 팝업이 표시.
    2. 사용자가 확인 버튼을 누르면:
      • yes로 전달된 showOk 함수가 실행. (즉, "동의하셨습니다." 팝업이 뜸)
    3. 사용자가 취소 버튼을 누르면:
      • no로 전달된 showCancel 함수가 실행. (즉, "취소 버튼을 누르셨습니다." 팝업이 뜸)

함수 ask의 인수, showOk와 showCancel은 콜백 함수라 불림.

 

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

자바스크립트에서 함수를 정의하는 방법에는 함수 선언문함수 표현식 두 가지가 있다.


1. 문법 차이

함수 선언문

function sum(a, b) {
  return a + b;
}
  • 함수 선언문은 독립적인 구문으로 작성
  • function 키워드로 바로 함수를 정의
  • 작성만 해도 함수가 바로 사용할 준비가 됨.

함수 표현식

let sum = function(a, b) {
  return a + b;
};
  • 함수 표현식은 값처럼 변수에 할당.
  • 함수는 = 연산자 오른쪽에 작성되며, 다른 변수나 데이터와 같이 취급됨.
  • 실행 흐름이 이 줄에 도달하기 전에는 사용 불가능함.

2. 사용 가능 시점의 차이

함수 선언문은 어디서든 호출 가능

  • 자바스크립트는 스크립트를 실행하기 전에 함수 선언문을 먼저 처리
  • 이 과정을 **호이스팅(hoisting)**이라고 부르며, 함수 선언문은 스크립트의 어느 위치에서든 호출할 수 있게 됨
console.log(sum(3, 4)); // 정상 작동, 출력: 7

function sum(a, b) {
  return a + b;
}

함수 표현식은 작성된 이후에만 호출 가능

  • 함수 표현식은 코드가 실행 흐름상 해당 줄에 도달했을 때 만들어짐.
  • 따라서 함수가 정의되기 전에 호출하면 오류가 발생함.

✍️핵심 요약

  • “함수 선언” 방식으로 함수를 생성하면, 함수가 독립된 구문 형태로 존재하게 됨.
  • “함수 표현식” 방식으로 함수를 생성하면, 함수가 표현식의 일부로 존재하게 됨.
  • 함수 선언문은 코드 블록이 실행되기도 전에 처리됩니다. 따라서 블록 내 어디서든 활용 가능함.
  • 함수 표현식은 실행 흐름이 표현식에 다다랐을 때 만들어짐.

 

💡화살표 함수

함수 표현식보다 단순하고 간결한 문법으로 함수를 만들 수 있는 방법이 있다.

⇒ 바로 **화살표 함수(arrow function)**를 사용하는 것

let func = function(arg1, arg2, ...argN) {
  return expression;
};

// 위 함수를 화살표 함수를 사용해 표현
let func = (arg1, arg2, ...argN) => expression
let sum = (a, b) => a + b;

/* 위 화살표 함수는 아래 함수의 축약 버전

let sum = function(a, b) {
  return a + b;
};
*/

alert( sum(1, 2) ); // 3

 

  • 인수가 하나도 없을 땐 빈 괄호
// 인수가 하나도 없을 땐 괄호 안 비우면 됨.
let sayHi = () => alert("안녕하세요!");

sayHi();

 

  • 본문이 여러 줄인 화살표 함수는 { } 안에 코드를 넣자!
let sum = (a, b) => {  // 중괄호는 본문 여러 줄로 구성되어 있음을 알려줍니다.
  let result = a + b;
  return result; // 중괄호를 사용했다면, return 지시자로 결괏값을 반환해주어야 합니다.
};

alert( sum(1, 2) ); // 3