서비스를 만들다 보면 같거나 비슷한 동작이 생기기 마련이다. 팝업창을 띄운다든지 결제할 때 같은. 이런 동작들을 자주 사용하거나 여러 곳에서 사용한다면 하나로 만든 다음 재사용하는 게 좋다. 그렇게 해야 중복되는 코드도 줄어들고 유지 보수도 편해지기 때문이다. 함수는 이때 쓰인다.
함수에는 브라우저가 이미 갖고 있는 console, alert, confirm도 포함된다.
함수는 이런 식으로 작성한다. 매개변수는 인수라고도 불리는데 완전히 동일한 의미라고는 할 수 없다. 매개변수는 없을 수도 있고, 지금처럼 한 개일 수도 있고, 두 개 이상일 수도 있다. 만약 매개변수가 여러 개라면 쉼표로 구분한다. 중괄호 내부에는 함수의 실행 코드를 작성한다. 지금은 간단히 이름을 받아 앞에 "Hello"를 붙이고 로그를 찍어주고 있다. 이 함수는 함수명 뒤에 괄호를 붙여 호출할 수 있다. 매개변수가 필요하다면 괄호 안에 넣는다.
에러 메시지를 보여주는 함수의 예. 괄호 안에 매개변수를 적는다. 매개변수는 없어도 되고, 두 개 이상이면 쉼표로 구분해서 여러 개를 받을 수 있다. 지금은 매개변수가 없어도 되니 빈 괄호를 넣는다. 그리고 중괄호를 열고 코드를 작성한다.
이 에러 메시지를 어떤 서비스의 수백 군데에서 쓰고 있다고 가정해보자. 로그인, api 호출, 결제 등을 실패할 때마다 저렇게 띄어주면 편할 것이다. 매번 길게 입력할 필요 없이 몇 글자면 처리되기 때문이다. 또 하나의 장점은 유지 보수가 쉽다는 것이다. 만약 기획자가 와서 뒤의 경고창 문구를 "새로고침 해주세요"로 바꿔달라고 한다면 어떨까. 이미 수백 군데에서 사용하고 있지만 이렇게 한 줄만 바꿔주면 된다.
이번에는 매개변수가 있는 함수를 작성해보자. 이름은 'sayHello'이고 'name'을 매개변수로 받는다. 앞에 'Hello'를 붙여주고 'name'을 써서 'msg'를 만든다. 결국 함수 사용의 목적은 중복을 줄이기 위해서이다. 함수를 한번 만들어놓으면 매개변수를 바꿔가며 다양하게 대응 가능하다.
만약 로그인하지 않아서 사용자의 이름을 모르는 경우는 어떻게 처리할까? 중괄호 내부에 조건문을 추가하면 된다. 'msg'를 let으로 바꾼 이유는 내용이 달라질 수 있기 때문이다. 일단 const로 변수를 선언하는 습관을 들이고 내용이 바뀔 가능성이 있으면 let으로 수정하면 된다. if(undefined)는 false이므로 중괄호 내부로 들어갈 수 없어서 메시지는 "Hello"로 찍힌다.
이런 식으로도 표현할 수 있다.
아니면 백틱을 써도 동일한 결과가 나온다.
여기에서 한 가지 중요한 사실은 변수 'msg'는 함수 밖에서 사용할 수 없다는 것이다. 함수 내부에서 사용하는 변수를 지역변수라고 하는데, 함수 안에서만 사용할 수 있다. 지역변수를 함수 밖에서 사용하면 에러가 발생한다.
만약에 이 'msg'를 함수 외부에서도 사용하고 싶다면 이렇게 함수 바깥으로 빼줘야 한다.
어디에서나 접근 가능한 변수를 전역변수(global variable)라고 한다. 함수 내부에서만 접근할 수 있는 변수를 지역변수(local variable)라고 한다.
한번 let으로 선언한 변수는 다시 let을 이용해 선언할 수 없다. 그런데 전역변수와 지역변수로 구분되어 있을 때는 어떨까.
콘솔로 찍어보면 이렇다. 첫 번째 'msg'는 전역변수이다. 그리고 두 번째 'msg'는 지역변수이다. 확인해보면 함수 내부에서 let으로 전역변수와 동일한 이름으로 선언할 수 있고, 서로 간섭받지 않는다.
다른 예를 살펴보자. 첫 번째 호출은 undefined가 나오고 두 번째에는 Jane이 나온다. 매개변수로 받은 값은 복사된 후 함수의 지역변수가 된다. 전체 서비스에서 공통으로 바라봐야 하는 서비스를 제외하고는 지역변수를 쓰는 습관을 들여야 한다. 전역변수가 많아지면 관리가 힘들어지기 때문이다. 가급적 함수에 특화된 지역변수를 사용해야 한다.
몇 가지 내용을 더 살펴보자. 앞서 'name'이 없을 때를 대비해 if문을 써줬다. 여기에서 OR 연산자를 활용하면 다음과 같다. 매개변수가 없으면 undefined가 나오기 때문에 OR 연산자를 거쳐 'name' 대신 'friend'를 반환한다. 반면 이름을 입력하면 입력한 이름이 나온다.
기본값을 설정해줄 수도 있다. 매개변수에 기본값을 설정하면 더 간단하게 대응할 수 있다. 이때 기본값은 name이 없을 때만 할당된다. 코드가 훨씬 간결해졌다.
어떤 값을 반환하는 함수를 만들어보자. 두 개의 숫자를 입력받아 더한 뒤 반환할 것이다. 반환은 return을 사용한다. 앞에 return을 적어주면 return 오른쪽에 있는 값을 반환한다. add 함수에 숫자 두 개를 넣어 호출하면 더한 다음 반환한다. 이 반환된 값은 변수 result에 들어가 있다. 사실 return이 없어도 뭔가를 반환한다.
이 함수는 아무것도 반환하지 않고 경고창만 띄워주고 있다.
이걸 result에 넣어주면 어떻게 될까? 경고창을 띄운 뒤 undefined를 반환한다. return문이 없는 함수도 항상 undefined를 반환한다.
return문이 없는 함수도 항상 undefined를 반환한다. 혹은 return만 있어도 undefined를 반환한다. 참고로 이렇게 return문이 있으면 그 즉시 return 오른쪽에 있는 값을 반환하고 종료한다. 그래서 함수를 종료하는 목적으로 사용하기도 한다.
함수는 한 번에 한 작업만 하는 게 좋다. 하나의 함수로 여러 작업을 동시에 진행하기보다는 함수를 잘게 나눠서 쓰는 편이 낫다. 변수도 마찬가지이지만 함수도 이름 짓는 게 상당히 중요하다. 읽기 쉽고 어떤 동작을 하는 건지 이름만 보고 알 수 있게 지어야 한다.
출처: 코딩앙마, 자바스크립트 기초 강좌 #10 - 함수(function)의 기초