스크립트를 공부하면서 가장 이해되지 않았던.. 함수를 차근차근 이해 해보겠습니다.🐰 모던 자바스크립트 함수
스크립트를 작성하다 보면 유사한 동작을 하는 코드가 여러 곳에서 필요할 때가 많습니다.
사용자가 로그인이나 로그아웃을 했을 때 안내 메시지를 보여주는 동작 같은 경우 말이죠.
함수는 프로그램을 구성하는 주요 '구성 요소(building block)'입니다.
함수를 이용하면 중복 없이 유사한 동작을 하는 코드를 여러 번 호출할 수 있습니다.
우리는 앞서 다양한 예시에서 alert(message), prompt(message, default), confirm(question)과 같은 내장 함수를 사용해 보았습니다.
이번엔 함수를 직접 만드는 방법에 대해 알아보겠습니다.
문자열이나 숫자 등의 일반적인 값들은 데이터를 나타냅니다.
함수는 하나의 동작(action)을 나타냅니다.
동작을 대변하는 값인 함수를 변수 간 전달하고, 동작이 필요할 때 이 값을 실행할 수 있습니다.
함수는 항상 무언가를 반환합니다.
<script>
function showMessage() {
alert( '안녕하세요!' );
}
</script>
<script>
function name(parameter1, parameter2, ... parameterN) {
// 함수 본문
}
</script>
<script>
function showMessage() {
alert( '안녕하세요!' );
}
showMessage();//호출
showMessage();//호출. 안녕하세요 alert창이 두 번 뜹니다.
</script>
(전에 썼던 범위 scope글도 뭔가 이상한 것 같다..🥺)
<script>
function showMessage() {
let message = "안녕하세요!"; // 지역 변수. 함수 내 입니다.
alert( message );
}
showMessage(); // 안녕하세요!
alert( message ); // ReferenceError: message is not defined
// (message는 함수 내 지역 변수이기 때문에 에러가 발생합니다. 밖에서 호출 했다.)
</script>
<script>
let userName = 'John';
function showMessage() {
let message = 'Hello, ' + userName;
alert(message);
}
showMessage(); // Hello, John
</script>
<script>
let userName = 'John';
function showMessage() {
userName = "Bob"; // (1) 외부 변수를 수정함
let message = 'Hello, ' + userName;
alert(message);
}
alert( userName ); // 함수 호출 전이므로 John 이 출력됨
showMessage(); //함수 호쯀!
alert( userName ); // 함수에 의해 Bob 으로 값이 바뀜
</script>
<script>
let userName = 'John';
function showMessage() {
let userName = "Bob"; // 같은 이름을 가진 지역 변수를 선언합니다.
let message = 'Hello, ' + userName; // Bob
alert(message);
}
// 함수는 내부 변수인 userName만 사용합니다,
showMessage();
alert( userName ); // 함수는 외부 변수에 접근하지 않습니다. 따라서 값이 변경되지 않고, John이 출력됩니다.
</script>
변수는 연관되는 함수 내에 선언하고, 전역 변수는 되도록 사용하지 않는 것이 좋습니다. 비교적 근래에 작성된 코드들은 대부분 전역변수를 사용하지 않거나 최소한으로만 사용합니다. 다만 프로젝트 전반에서 사용되는 데이터는 전역 변수에 저장하는 것이 유용한 경우도 있으니 이 점을 알아두시기 바랍니다.
<script>
function showMessage(from, text) { // 매개 변수(인자): from, text. 2. 지역변수 from, text에 복사됩니다.
alert(from + ': ' + text);
}
showMessage('Ann', 'Hello!'); // Ann: Hello! (*) 1. 함수에 전달된 인자는?
showMessage('Ann', "What's up?"); // Ann: What's up? (**)
</script>
<script>
function showMessage(from, text) {
from = '*' + from + '*'; // 2. 전역 변수 from을 함수에 전달하였습니다.
// 3. showMessage 함수가 from을 변경(재할당) 하지만?(*Ann*으로 변경)
alert( from + ': ' + text );
}
let from = "Ann"; // 1. 전역 변수 from이 있고
showMessage(from, "Hello"); // *Ann*: Hello
// 함수는 복사된 값을 사용하기 때문에 바깥의 "from"은 값이 변경되지 않습니다.
alert( from ); // Ann. 4. 변경 사항은 외부 변수 from에 반영되지 않았습니다.
</script>
함수의 매개변수에 전달된 값을 *인수(argument)*라고 부르기도 합니다.
매개변수는 함수 선언 방식 괄호 사이에 있는 변수입니다(선언 시 쓰이는 용어).
인수는 함수를 호출할 때 매개변수에 전달되는 값입니다(호출 시 쓰이는 용어).<script> //함수 선언 function showMessage(from, text) { // 매개변수(인자) alert(from + ': ' + text); } //함수 호출 showMessage('Ann', 'Hello!'); // 인수 </script>
<script>
//함수 선언
showMessage(from, text){
//실행문
};
//함수 호출
showMessage("Ann");
</script>
매개변수에 값을 전달하지 않아도 그 값이 undefined가 되지 않게 하려면 함수를 선언할 때 =를 사용해 '기본값(default value)'을 설정해주면 됩니다.
<script>
function showMessage(from, text = "no text given") {
alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given
</script>
매개변수에 값을 전달해도 그 값이 undefined와 엄격히 일치한다면 기본값이 할당됩니다.
<script>
showMessage("Ann", undefined); // Ann: no text given
</script>
복잡한 표현식도 기본값으로 설정할 수도 있습니다.
<script>
function showMessage(from, text = anotherFunction()) {
// anotherFunction()은 text값이 없을 때만 호출됨
// anotherFunction()의 반환 값이 text의 값이 됨
}
</script>
<script>
// 매개변수 'count'가 `undefined` 또는 `null`이면 'unknown'을 출력해주는 함수
function showCount(count) {
alert(count ?? "unknown");
}
showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown
</script>
<script>
function sum(a, b) {
return a + b;
}
let result = sum(1, 2);
alert( result ); // 3
</script>
<script>
function checkAge(age) { // 함수 선언. 매개 변수 age ?2.여기로 전달
if (age >= 18) { // age가 18 이상이면
return true; // true를 반환
} else { // 이외는 confirm창 띄움
return confirm('보호자의 동의를 받으셨나요?');
}
}; // 여기까지 checkAge 함수 선언
let age = prompt('나이를 알려주세요', 18); // 변수 age = 입력창. ?1.이 값을?
if ( checkAge(age) ) { // checkAge 함수가 true면
alert( '접속 허용' ); // 접속 허용 alert창 띄움
} else { // 이외(false)면 접속 차단 alert창 띄움
alert( '접속 차단' );
}; // 여기까지 if문
</script>
<script>
let age = prompt("나이를 알려주세요", 18);
if (age >= 18) {
alert("접속 허용");
} else {
let agree = confirm("보호자의 동의를 받으셨나요?");
if (agree) {
alert("접속 허용");
} else {
alert("접속 차단");
}
}
</script>
<script>
function showMovie(age) {
if ( !checkAge(age) ) {
return;
}
alert( "영화 상영" ); // (*)
// ...
}
</script>
return은 반복문의 break 키워드와 비슷한 역할을 하는걸까요?🤔
<script>
function doNothing() { /* empty */ }
alert( doNothing() === undefined ); // true
</script>
<script>
function doNothing() {
return;
}
alert( doNothing() === undefined ); // true
</script>
❗️return과 값 사이엔 줄바꿈❌
1. 이 코드는? <script> return (some + long + expression + or + whatever * f(a) + f(b)) </script> --- 2. 이 코드로 동작합니다. 따라서 반환하고자 했던 표현식을 반환하지 못하고 아무것도 반환하지 않는 것처럼 되어버립니다. <script> return; (some + long + expression + or + whatever * f(a) + f(b)) </script> --- 3. 표현식을 여러 줄에 걸쳐 작성하고 싶다면 표현식이 return 지시자가 있는 줄에서 시작하도록 작성해야 합니다. 또는 아래와 같이 여는 괄호를 return 지시자와 같은 줄에 써줘도 괜찮습니다. <script> return ( some + long + expression + or + whatever * f(a) + f(b) ) </script>
함수는 어떤 동작을 수행하기 위한 코드를 모아놓은 것입니다.
따라서 함수의 이름은 대개 동사입니다.
함수 이름은 가능한 한 간결하고 명확해야 합니다. 함수가 어떤 동작을 하는지 설명할 수 있어야 하죠.
코드를 읽는 사람은 함수 이름만 보고도 함수가 어떤 기능을 하는지 힌트를 얻을 수 있어야 합니다.
함수가 어떤 동작을 하는지 축약해서 설명해 주는 동사를 접두어로 붙여 함수 이름을 만드는 게 관습입니다.
"show"로 시작하는 함수는 대개 무언가를 보여주는 함수입니다.
이 외에 아래와 같은 접두어를 사용할 수 있습니다.
<script>
showMessage(..) // 메시지를 보여줌
getAge(..) // 나이를 나타내는 값을 얻고 그 값을 반환함
calcSum(..) // 합계를 계산하고 그 결과를 반환함
createForm(..) // form을 생성하고 만들어진 form을 반환함
checkPermission(..) // 승인 여부를 확인하고 true나 false를 반환함
</script>
🔧 함수는 동작 하나만 담당해야 합니다.
함수는 함수 이름에 언급되어 있는 동작을 정확히 수행해야 합니다. 그 이외의 동작은 수행해선 안 됩니다.
- 예시)
- getAge 함수는 나이를 얻어오는 동작만 수행해야 합니다. alert 창에 나이를 출력해 주는 동작은 이 함수에 들어가지 않는 것이 좋습니다.
- createForm 함수는 form을 만들고 이를 반환하는 동작만 해야 합니다. form을 문서에 추가하는 동작이 해당 함수에 들어가 있으면 좋지 않습니다.
- checkPermission 함수는 승인 여부를 확인하고 그 결과를 반환하는 동작만 해야 합니다. 승인 여부를 보여주는 메시지를 띄우는 동작이 들어가 있으면 좋지 않습니다.
깔끔하고 이해하기 쉬운 코드를 작성하려면 함수 내부에서 외부 변수를 사용하는 방법 대신 지역 변수와 매개변수를 활용하는 게 좋습니다.
요약:
“함수 선언(문)” 방식으로 함수를 생성하면, 함수가 독립된 구문 형태로 존재하게 됩니다.
“함수 표현식” 방식으로 함수를 생성하면, 함수가 표현식의 일부로 존재하게 됩니다.
함수 선언문은 코드 블록이 실행되기도 전에 처리됩니다. 따라서 블록 내 어디서든 활용 가능합니다.
함수 표현식은 실행 흐름이 표현식에 다다랐을 때 만들어집니다.
함수를 선언해야 한다면 함수가 선언되기 이전에도 함수를 활용할 수 있기 때문에,
함수 선언문 방식을 따르는 게 좋습니다.
함수 선언 방식은 코드를 유연하게 구성할 수 있도록 해주고, 가독성도 좋습니다.
함수 표현식은 함수 선언문을 사용하는게 부적절할 때에 사용하는 것이 좋습니다.