코드를 저장해서 필요한곳에 호출해 사용할 수 있다.
반복적인 작업이 간소화되며 가독성이 좋아집니다.
브라우저상에서 자주 호출되는 함수는 alert
prompt
confirm
등이 있습니다.
함수 또한 객체이며, 일급객체로 분류되고 일반적인 객체와 다른 점은 호출이 가능.
❤️ 문법
function showMessage() { // 키워드(function) 함수이름(showMessage) 매개변수() 현재 없음
alert('안녕하세요!'); // 함수 본문 ( 함수를 호출하면 작동하는 코드 )
}
/* */
함수 선언 방식 : function(키워드), 함수 이름, (매개변수), { 함수 본문 }
function : 함수를 선언하는 키워드 ( 변수를 선언하는 let과 동일하다 )
함수 이름 : 함수에 이름을 정해줍니다 ( 변수명과 동일하다 )
매개 변수 : 함수를 호출할 때 인수값을 인자로 받는 변수, 값들은 컴마로 구분한다.
함수 본문 : 함수를 호출할 때, 실행되는 코드들이 여기에 포함된다.
❤️ 함수 사용
function showMessage() {
alert('안녕하세요!');
}
showMessage();
showMessage();
/* */
showMessage()
1) showMessage 라는 함수를 호출합니다.
2) 함수를 호출하면, 함수본문에 있는 코드가 실행됩니다.
3) 2번 호출 하였으므로, 함수본문에 있는 alert('안녕하세요!')가 2번 출력됩니다.
코드 확인
함수의 장점은 중복처리되는 코드를 정의해서 간단하게 사용할 수 있습니다.
함수는 호이스팅 특성으로 인해, 어떤 코드라인에서 선언하든지 항상 코드의 최상단에
선언된 것으로 간주 됩니다.
함수를 선언하기 이전에 호출해도 문제가 발생하지 않는다.
호이스팅 참조
함수 선언문에만 해당되며, 함수 표현식에서는 호이스팅이 발생하지 않습니다.
hoisting();
hoisting();
function hoisting(){
console.log('호이스팅 !');
}
/*
함수를 선언하기 이전에 호출해도, 함수가 선언되면 코드를 실행하기 이전에 검사하는 과정에서
함수를 코드의 최상단 부분으로 끌어 올리므로 사실상 선언이 호출보다 읽히게 됩니다.
* 호이스팅으로 인해, 함수 선언부분이 코드의 최상단 부분으로 올라간다 *
function hoisting(){
console.log('호이스팅 !');
}
hoisting();
hoisting();
*/
함수 내에서 선언한 변수를 지역변수라고 합니다.
지역 변수는 함수 내부에서만 접근할 수 있습니다.
❤️ 지역변수
function showMessage () {
let message = "지역변수 입니다";
alert(message);
}
showMessage(); // '지역변수 입니다' 출력
alert(message); // 코드 오류
/*
showMessage() 함수 내부에서 선언된 message 변수는 지역변수라고 합니다.
함수 내부에서 선언된 변수는, 함수 밖을 벗어나면 사용할 수 없습니다.
함수 밖에서 let message; 라고 변수를 선언하면 이는 지역변수와는 완전하게 다른
변수입니다.
*/
함수 밖에 있는 변수를 전역변수 또는 외부변수라고 합니다.
함수 내부에서 전역 변수를 호출해서 수정할 수 있습니다.
❤️ 전역변수
let userName="John"; // 전역 변수
function showMessage () {
let message ="Hello" + userName; // 함수 내부에서 전역변수를 호출
alert(message);
}
showMessage(); // Hello John이 출력 됨
❤️ 전역변수를 함수 내부에서 수정하기
let userName="John"; // 전역변수
function showMessage() {
userName = "Eunji"; // 전역 변수 UserName을 호출하고 수정할 수 있다.
let message = "Hello" + userName;
alert(message); // Hello EunJi가 출력 됩니다.
}
alert(userName) // 함수 호출 전, John이 출력 됩니다.
showMessage() // Hello Eunji가 출력 됩니다.
alert(userName) // 함수 호출 이후, 함수에서 수정된 전역변수가 호출됩니다 (EunJi)
/* */
1) 전역에 설정된 전역 변수를 함수에서 호출해서 사용할 수 있다.
2) 전역변수를 호출해서 수정하면, 전역 변수의 데이터도 수정된다.
❤️ 전역변수와 지역변수명이 동일할 때
let userName = 'John ';
function showMessage () {
let userName = 'BoB'; // 외부변수명과 동일하기에, 지역변수가 덮어 씌웁니다.
let message = "Hello" + userName;
alert(message); // Hello BoB
}
alert(userName) // John 출력
showMessage(); // Hello BoB 출력
alert(userName) // John 출력 ( 지역변수가 전역변수를 덮어씌웠기에, 전역변수의 값이 변경되지 않았습니다 )
/* */
1) 전역변수와 지역변수의 변수명이 똑같다면 서로 다른 변수가 된다.
2) 서로 다른 변수기에 함수에서 전역변수를 수정할 수 없다.
함수 밖에서 함수를 호출할 때, 실제 데이터가 있는 인수(argument)를 함수에게 전달할 수
있습니다.
함수는 인수를 전달받기 위해 매개변수(인자)를 생성해서 값을 저장합니다.
인수를 전달받는 인자를 매개변수라고 합니다.
❤️ 매개변수 (인자)
function showMessage(from, text) { // 인자 : from, text
alert(from + ': ' + text);
}
showMessage('Ann', 'Hello!'); // 인수 : 'Ann' 'Hello'
showMessage('Ann', "What's up?"); // 인수 : 'Ann' 'What's up?'
/*
1. 본문에서 인수값을 전달해서 함수를 호출.
2. 함수는 인수값을 전달받을 매개변수를 생성
3. alret 메서드에 매개변수를 호출합니다.
4. from과 text 매개변수에 실제로 저장되있는 인수값을 사용합니다.
5. 출력 : 'Ann: Hello!' , 'Ann: What"s up?'
*/
/*
array.index('h') 같이 메서드에서도 인수가 사용됩니다 ( 여기서 인수는 'h' )
*/
❤️ 매개변수는 인수를 복사해서 사용한다.
function showMessage(from, text) { // 매개변수 from, text
from = '*' + from + '*'; // from = *Ann*, 매개변수 수정
alert( from + ': ' + text ); // *Ann*: Hello 출력
}
let from = "Ann"; // 전역변수 from 선언
showMessage(from, "Hello"); // 함수호출, 인수로 전역변수 from과 "Hello" 전달
alert( from ); // Ann 출력, 바뀌지 않는다.
/*
from이라는 전역변수를, 함수에서 매개변수로 받아오는 것이 아니라 단순하게 호출했다면
값을 수정할 수 있습니다. 하지만 매개변수로 받아오는 인수 값은 전역변수를 호출하는 것이 아닌
값을 복사해서 오는 것이므로 값을 수정해도, 원본의 인수 값은 바뀌지 않습니다.
*/
함수는 매개변수가 없거나, 매개변수가 인수를 전달받지 못하면 기본 값으로 undefined
를
할당 합니다.
undefined
이외의 다른 값을 기본 값으로 사용하고 싶을 때 기본 값을 정의할 수 있습니다.
❤️ 매개변수 기본 값 정의
function showMessage(from, text = "no text given") { // 매개변수 text에 기본값을 지정
alert( from + ": " + text ); // "Ann: no text given" 호출 됨
}
showMessage("Ann"); // 함수 호출, 인수를 1개만 전달합니다.
/* */
함수에 from 매개변수는 인수를 전달받지만, text 매개변수는 인수를 전달받지 못합니다.
이 때 기본 값으로 정해놓은 "no text given"이 text 매개변수에 할당됩니다.
만약 text 매개변수도 인수를 전달 받았다면, 인수의 값으로 할당되었을 겁니다.
❤️ 매개변수의 기본 값은 함수도 가능
function showMessage(from, text = anotherFunction()) {
// 매개변수의 기본 값을 다른 함수의 반환 값으로 할당할 수 있습니다.
// 다른 함수의 반환 값이 text 매개변수로 할당됩니다.
}
❤️ 함수 본문에서 기본 값을 정의 할 수 있음
function showMessage(text) {
if (text === undefined) {
text = '빈 문자열';
}
alert(text);
}
showMessage(); // 빈 문자열
/* */
text 매개변수의 값이 undefined라면 (인수를 받지 못했다면) text 매개변수에 '빈 문자열' 값을 할당합니다.
때로는 함수 내부에서 매개변수의 기본 값을 설정해주는 것이 더 적합한 경우도 있습니다.
* 1. ----------------------------------------------------------------------
function showMessage(text) {
text = text || '빈 문자열';
alert(text);
}
showMessage(); // 빈 문자열
/* */
text 매개 변수의 값이 거짓 된 값이라면 '빈 문자열' 출력
거짓된 값 : '' 빈 문자열, null , undefined, 숫자 0
* 2. ----------------------------------------------------------------------
function showMessage(text) {
text = text ?? '빈 문자열'; // 피 연산자가 null이나 undefined가 아니라면 반환
alert(text);
}
showMessage(0); // 출력 : 0
showMessage(null); // 출력 : '빈 문자열'
showMessage(); // 출력 : '빈 문자열'
/* */
1) text가 0이나 공백같은 빈 문자열이라면, 그 값을 text 변수에 반환
2) text가 null이나 undefined라면 '빈 문자열'이 반환 된다.
함수에 지역변수와 전역변수처럼, 조건문이나 반복문에서 변수를 할당하면 해당 문
범위 밖에서는 접근할 수 없습니다.
함수
var 선언자
는 문단을 선언하면 반복문이나 조건문등 블럭 안에서 선언해도
전역에서 호출해서 사용할 수 있습니다.
let
또는 const
선언자는 블럭 밖에서는 사용할 수 없다.
let redius = 8;
if(radius > 0) {
const PI = 3.14159;
let msg = 'HIII';
}
console.log(PI);
console.log(msg);
/* 접근 불가. 오류 */
/* var 변수를 사용하면 블럭 밖에서 호출할 수 있다 */
if(radius > 0) {
var PI = 3.14159;
var msg = 'HIII';
}
console.log(PI); // 3.14159
console.log(msg); // 'HIII'
return
지시자return
을 사용하면 실행중인 명령을 즉시 종료하고, 자신을 호출한 함수로 값을 반환합니다.
반환될 때 값은 한 가지의 값만 반환합니다. 여러 가지의 값을 반환하고 싶다면 배열을
사용해야 합니다. 다만 배열도 1개여야 한다.
❤️ 형식
function sum(a, b) { // 매개변수에서 전달받은 인수 값 저장 ( 1,2 )
return a + b; // a와 b를 더하고 자신을 호출한 함수에게 값을 반환합니다.
}
let result = sum(1, 2); // 인수로 1과 2를 전달합니다.
alert( result ); // 출력 : 3
❤️ return 지시자의 위치는 자유롭게 사용 가능
function checkAge(age) { // 3. 인수로 전달받은 값을 매개변수 age에 저장 (18)
if (age >= 18) { // 4. age(18)값은 18보다 크거나 같으므로 조건문은 참
return true; // 5. 함수를 즉시 종료합니다. 돌아갈 때 true값을 반환
} else {
return confirm('보호자의 동의를 받으셨나요?'); // 번외. 사용자가 입력값이 18보다 작다면
// 질문 메세지를 한 번 더 수행한다. (확인/취소)
// 확인을 누르면 true값이 반환, 취소를 누르면 false를 반환
}
}
let age = prompt('나이를 알려주세요', 18); // 1. 전역 변수 선언
if ( checkAge(age) ) { // 2. 함수호출 ( 인수 : age 전달 ), 조건문은 checkAge 함수의 반환값으로 확인한다.
alert( '접속 허용' ); // 5. 조건문이 참이기 때문에, '접속 허용' 메세지가 출력
} else {
alert( '접속 차단' ); // 6. 조건문이 거짓이라면, '접속 차단' 메세지가 출력
}
❤️ return 지시자만 사용 (위 구문이랑 이어집니다)
function showMovie(age) {
if ( !checkAge(age) ) {
return;
}
alert( "영화 상영" ); // (*)
// ...
}
/* */
showMovie 함수에서 checkAge(age)의 반환 값을 확인 합니다. !(Not) 논리 연산자로 인해서
참이라면 거짓으로, 거짓이라면 참으로 반환합니다.
만약, 거짓 값이 오면 참으로 반환되어 함수를 즉시 종료합니다. ( 영화상영 메세지 출력 X )
참의 값이 오면, 거짓으로 반환되어 조건문을 수행하지 않고, alert를 수행합니다 ( " 영화 상영 " )
❗ 즉, else절이 필요 없다.
⚠️
undefined
자료형이 반환되는 경우 두 가지
1) 매개 변수의 값이 없는 경우function doNothing() { /* empty */ } / alert( doNothing() === undefined ); // true /* 매개변수의 값이 없다면 undefined가 할당 된다 */
2) return 지시자에 반환 값이 없는 경우function doNothing() { return; } / alert( doNothing() === undefined ); // true // return 지시자만 반환 할 경우에는, undefined를 반환한다.
⚠️ return 지시자 주의사항
✔️return
지시자를 사용해서 연산결과를 반환 값으로 가져갈 때 주의사항은
연산이 시작되는 부분은 지시자와 같은 라인에 있어야 합니다.
✔️return
지시자는 문 끝에 자동으로;
(세미콜론)이 붙기 때문에, 표현식을 표현하고
싶다면 표현식의 시작위치는 항상 지시자와 같은 라인에서 시작해야 합니다.
❌ 올바르지 않은 사용 법return ( a+b ) a+b의 연산 결과를 반환으로 가져가지 않습니다. 연산의 시작 부분이 return과 다른 라인에 있기 때문에 인식하지 않습니다.
⭕ 올바른 사용 법return ( <= 연산의 시작은 return 지시자와 같은라인에 있어야 한다. a + b ) a+b의 연산 결과를 반환 값으로 가져 갑니다.
중첩된 함수나 내부 함수는 상위 몇 레벨 위에 있던 상관없이 부모 함수나 조부모 함수등에
있는 변수등을 접근해서 호출할 수 있습니다.
다만 역으로, 중첩함수 내부에 있는 변수는 상위레벨의 함수에서는 접근할 수 없다.
function bankRobbery() {
let herose = ['chulsu', 'Spiderman', 'Wolverine', 'Black Panther'];
function cryForHelp() {
function inner() {
for (let hero of herose) { // 중첩함수는 조부모의 배열의 접근 가능
console.log(`${hero} HI`)
}
}
inner(); // 두번째 중첩함수
}
cryForHelp(); // 첫번째 중첩함수
}
bankRobbery();
/*
출력
chulsu HI
Spiderman HI
Wolverine HI
Black Panther HI
*/
/* 중첩 함수에서 선언한 변수는, 상위 레벨의 함수에선 접근할 수 없다*/
function bankRobbery() {
let herose = ['chulsu', 'Spiderman', 'Wolverine', 'Black Panther'];
console.log(color); // 오류 발생
function cryForHelp() {
let color = 'blue'; // 중첩 함수에서 변수 선언
function inner() {
for (let hero of herose) {
console.log(`${hero} HI`)
}
}
inner(); // 두번째 중첩함수
}
cryForHelp(); // 첫번째 중첩함수
}
함수의 이름은 유의미하고 가능한 간결하게 정의해야 한다.
함수는 동작과 관련된 코드의 집합체로 함수명은 동작에 관련된 이름으로 정의합시다.
함수명 | 내용 |
---|---|
show.. | show로 시작하는 함수명은, 메세지를 보여줍니다 |
get.. | 무언가의 값을 반환합니다 |
calc.. | 무언가를 계산합니다. |
create.. | 무언가를 생성합니다. |
check.. | 무언가를 확인하고 boolean값을 반환합니다. |
showMessage(..) // 메시지를 보여줌
getAge(..) // 나이를 나타내는 값을 얻고 그 값을 반환함
calcSum(..) // 합계를 계산하고 그 결과를 반환함
createForm(..) // form을 생성하고 만들어진 form을 반환함
checkPermission(..) // 승인 여부를 확인하고 true나 false를 반환함
함수는 특정한 동작을 구현하기 위한 코드의 집합체입니다.
함수에는 동작 1개만을 위한 코드를 구현하는게 좋습니다.
하나의 함수에 1개 이상의 동작이 필요하다면, 함수도 1개 이상 생성해서 각 함수당 1개의
동작만 구현할 수 있게 함수를 여러 개로 분리하는게 좋습니다.
분리된 함수는 자신이 어떤 역할을 하는지 유의미한 함수명을 작성하는걸 권장합니다.
function showPrimes(n) {
nextPrime: for (let i = 2; i <= n; i++) {
for (let j = 2; j < i; j++) {
if (i % j == 0) continue nextPrime;
}
alert( i ); // 소수
}
}
/* */
1) 사용자가 입력한 값을 토대로, 그 값에 대한 모든 소수를 구하는 함수입니다.
2) 함수는 2가지 동작을 합니다. 사용자로부터 입력받은 값만큼 반복하는 i 반복문
i 반복문의 값을 나눠서 소수를 구하는 j 반복문
3) 사용자가 입력한 값까지 소수를 구해야 하므로, j 반복문은 사용자가 입력한 값 까지
반복 수행하는 i 반복문을 나누면 됩니다.
하나의 함수에서 2가지 동작을 하므로, 함수를 분리해서 구현 해보겠습니다.
----------------------------------------------------------------
let n = prompt('값을 입력하세요','');
showPrimes(n);
function showPrimes(n) {
for(let i=2; i<=n; i++) {
if( isPrime(i) ) alert(i); // isprime 함수 호출, 인수 전달 (i), 반환 값이 참이라면 수행
}
}
/* 첫 번째 반복문의 카운터변수를 매개변수 n로 저장해서 자신의 반복문으로 n을 반복해서 나눈다.*/
function isPrime(n) {
for(let i=2; i<n; i++) { // 소수를 구하는 과정
if(n % i == 0) return false; // n이 i로 나눠진다면 소수가 아니므로 거짓 반환
}
return true; // if문이 만족하지 않으면 소수이므로 참을 반환
}
/* */
소수는 자신과 1이외의 다른 수로 나눌 수 없는 수 입니다.
즉 1과 자신을 제외한 숫자로 나눠진다면 소수가 아닙니다. 그러므로 거짓을 반환해서
alert창이 출력되지 않게 해줍니다. => if (n % i ==0) return false;
return
지시자를 통해 중간에 함수를 빠져나올 수 있다.return
지시자가 필수지만, 반환이 필요return
을 사용하지 않아도 된다.function sum(a,b) {
return a+b; // a와 b의 덧셈결과를 반환 하려면 return이 필수다. 없으면 반환 안됨
}
sum(1,2);
function num(value, yes, no) {
if( value ) yes(); // alert 함수의 출력만 필요한 경우, return 필요 없음
else no(); // 이하 동문
}
function truthy() {
alert('나는 사람입니다');
}
function falsy() {
alert('나는 사람이 아닙니다');
}
num( confirm('당신은 사람입니까?'), truthy, falsy); // 함수 호출