condition(조건)이 truthy이면 반복문 본문의 코드가 실행된다.
반복문 본문이 한 번 실행되는 것을 반복(iteration)이라고 부른다.
브라우저는 무한 반복을 멈추게 하는 실질적인 수단을 제공.
반복문 조건에는 비교뿐만 아니라 모든 종류의 표현식, 변수가 올 수 있다.
조건은 While에 의해 평가되고, 평가 후에는 불린값으로 변경된다.
let i = 3;
while (i) { // i가 0이 되면 조건이 falsy가 되므로 반복문이 멈춥니다.
alert( i );
i--;
}
condition을 반복문 본문 아래로 옮길 수 있다.
본문이 먼저 실행되고, 조건을 확인한 후 조건이 truthy인 동안에 본문이 계속 실행된다.
let i = 0;
do {
alert( i );
i++;
} while (i < 3);
조건의 참 여부에 관련없이 본문을 최소한 한 번이라도 실행하고 싶을 때 사용.
대다수 상황에서는 do while 문 보다는 while문이 적합하다.
for문을 구성하는 각 요소
for (begin; condition; step) {
// ... 반복문 본문 ...
}
for (let i = 0; i < 3; i++) { // 0, 1, 2가 출력됩니다.
alert(i);
}
begin이 한 차례 실행된 이후에 condition 확인과 body, step 이 계속돼서 반복 실행된다.
// for (let i = 0; i < 3; i++) alert(i)
// begin을 실행함
let i = 0
// condition이 truthy이면 → body를 실행한 후, step을 실행함
if (i < 3) { alert(i); i++ }
// condition이 truthy이면 → body를 실행한 후, step을 실행함
if (i < 3) { alert(i); i++ }
// condition이 truthy이면 → body를 실행한 후, step을 실행함
if (i < 3) { alert(i); i++ }
// i == 3이므로 반복문 종료
for문의 구성 요소를 생략하는 것 또한 가능.
반복문이 시작될 때 아무것도 할 필요가 없으면 begin이나 step 을 생략할 수 있다.
let i = 0;
for (; i < 3;) {
alert( i++ );
}
모든 구성 요소를 생략하면 무한 반복문이 만들어진다.
for (;;) {
// 끊임 없이 본문이 실행됩니다.
}
반복문의 조건이 falsy가 되면 반복문이 종료된다.
break
를 사용하면 언제든 원할 때 반복문을 빠져나올 수 있다.
let sum = 0;
while (true) {
let value = +prompt("숫자를 입력하세요.", '');
if (!value) break; // (* 아무것도 입력하지 않거나 cancel 누르면 종료)
sum += value;
}
alert( '합계: ' + sum );
이때 반복문은 즉시 중단되고 제어 흐름이 아래 첫번째 줄 (alert)로 이동하게 된다.
여러 곳에서 조건을 확인해야 하는 경우, '무한 반복문 + break' 조합을 사용하면 좋다.
continue
지시자는 break의 가벼운 버전.
전체 반복문을 멈추지 않는다.
현재 실행 중인 이터레이션을 멈추고 반복문이 다음 이터레이션을 강제로 실행시킴.
중첩을 줄일 때 도움이 된다.
현재 반복을 종료시키고 다음 반복으로 넘어가고 싶을 때 사용.
for (let i = 0; i < 10; i++) {
// 조건이 참이라면 남아있는 본문은 실행되지 않습니다.
if (i % 2 == 0) continue;
alert(i); // 1, 3, 5, 7, 9가 차례대로 출력됨
}
i가 짝수이면 contine가 본문 실행을 중단시키고 다음 이터레이션이 실행되게 한다.
즉, alert 함수는 인수가 홀수일 때만 호출된다.
여러 개의 중첩 반복문을 한 번에 빠져나올 때가 생김.
중첩 반복문을 빠져나와 바깥의 반복문으로 갈 수 있게 해주는 유일한 방법.
레이블: 반복문 앞에 콜론과 함계 쓰이는 식별자.
labelName: for (...) {
...
}
반복문 안에서 break <labelName>
문을 사용하면 레이블에 해당하는 반복문을 빠져나올 수 있다.
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
let input = prompt(`(${i},${j})의 값`, '');
// 사용자가 아무것도 입력하지 않거나 Cancel 버튼을 누르면 두 반복문 모두를 빠져나옵니다.
if (!input) break outer; // (*)
// 입력받은 값을 가지고 무언가를 함
}
}
alert('완료!');
break outer 는 outer 라는 레이블이 붙은 반복문을 찾고, 해당 반복문을 빠져나오게 해준다.
제어 흐름이 (*)에서 alert('완료')로 바뀌게 됨.
break, continue는 반복문 안에서만 사용할 수 있고, 레이블은 반드시 break 나 continue 지시자 위에 있어야 한다.
복수의 if 조건문은 switch문으로 바꿀 수 있다.
특정 변수를 다양한 상황에서 비교할 수 있게 해준다.
switch문은 하나 이상의 case 문으로 구성되고 default문(필수 X) 이 존재하기도 한다.
let a = 2 + 2;
switch (a) {
case 3:
alert( '비교하려는 값보다 작습니다.' );
break;
case 4:
alert( '비교하려는 값과 일치합니다.' );
break;
case 5:
alert( '비교하려는 값보다 큽니다.' );
break;
default:
alert( "어떤 값인지 파악이 되지 않습니다." );
}
case 문 안에 break 문이 없으면 조건에 부합하는지 여부를 따지지 않고 이어지는 case 문을 실행한다.
switch문과 case 문의 인수에는 어떤 표현식이든 올 수 있다.
let a = "1";
let b = 0;
switch (+a) {
case b + 1:
alert("표현식 +a는 1, 표현식 b+1는 1이므로 이 코드가 실행됩니다.");
break;
default:
alert("이 코드는 실행되지 않습니다.");
}
코드가 같은 case 문은 한데 묶을 수가 있다.
case 3: // (*) 두 case문을 묶음
case 5:
alert('계산이 틀립니다!');
alert("수학 수업을 다시 들어보는걸 권유 드립니다.");
break;
switch문은 일치 비교로 조건을 확인한다.
비교하려는 값과 case문의 값의 형과 갑이 같아야 해당 case 문이 실행된다.
let arg = prompt("값을 입력해주세요.");
switch (arg) {
case '0':
case '1':
alert( '0이나 1을 입력하셨습니다.' );
break;
case '2':
alert( '2를 입력하셨습니다.' );
break;
case 3:
alert( '이 코드는 절대 실행되지 않습니다!' );
break;
default:
alert( '알 수 없는 값을 입력하셨습니다.' );
}
3을 입력하더라도 prompt 함수는 입력 필드에 사용자가 기재된 값을 문자열로 변환해 반환하기 때문에 문자열 '3'을 반환한다.
문자열과 숫자형을 비교하기 때문에 case 3의 코드는 절대 실행되지 않고 대신 default문이 실행된다.
함수 : 프로그램을 구성하는 주요 구성 요소 (building block)
중복 없이 유사한 동작을 하는 코드를 여러 번 호출 가능.
함수 선언 방식 = 함수 선언문
function showMessage() {
alert( '안녕하세요!' );
}
function 키워드, 함수 이름, 괄호로 둘러싼 매개변수를 차례로 쓰면 함수를 선언할 수 있다.
함수를 구성하는 코드의 모임인 '함수 본문(body)을 중괄호로 감싸 붙여줌.
함수를 실행할 때는 showMessage()
로 함수를 호출할 수 있다.
함수의 주요 용도 중 하나는 중복 코드를 피하는 것에 있다.
function showMessage() {
let message = "안녕하세요!"; // 지역 변수
alert( message );
}
showMessage(); // 안녕하세요!
alert( message ); // ReferenceError: message is not defined (message는 함수 내 지역 변수이기 때문에 에러가 발생합니다.)
let userName = 'John';
function showMessage() {
userName = "Bob"; // (1) 외부 변수를 수정함
let message = 'Hello, ' + userName;
alert(message);
}
alert( userName ); // 함수 호출 전이므로 John 이 출력됨
showMessage();
alert( userName ); // 함수에 의해 Bob 으로 값이 바뀜
외부 변수는 지역 변수가 없는 경우에만 사용할 수 있다.
외부 변수와 동일한 이름을 가진 변수가 함수 내부에 있다면 내부 변수는 외부 변수를 가린다.
let userName = 'John';
function showMessage() {
let userName = "Bob"; // 같은 이름을 가진 지역 변수를 선언합니다.
let message = 'Hello, ' + userName; // Bob
alert(message);
}
// 함수는 내부 변수인 userName만 사용합니다,
showMessage();
alert( userName ); // 함수는 외부 변수에 접근하지 않습니다. 따라서 값이 변경되지 않고, John이 출력됩니다.
함수 내부에 외부 변수와 동일한 이름을 가진 지역 변수 userName이 선언되었기 때문에 외부 변수는 내부 변수에 가려져 값이 수정되지 않음.
전역 변수(global variable): 함수 외부에 선언된 변수
매개변수를 이용하면 임의 데이터를 함수 안에 전달할 수 있음.
인자라고 부르기도 함.
함수 선언 시 매개변수를 나열하게 되고, 함수를 호출할 땐 인수를 전달해 호출.
function showMessage(from, text) {
from = '*' + from + '*'; // "from"을 좀 더 멋지게 꾸며줍니다.
alert( from + ': ' + text );
}
let from = "Ann";
showMessage(from, "Hello"); // *Ann*: Hello
// 함수는 복사된 값을 사용하기 때문에 바깥의 "from"은 값이 변경되지 않습니다.
alert( from ); // Ann
함수 호출 시 매개변수에 인수를 전달하지 않으면 undefined를 반환한다.
매개변수에 값을 전달하지 않아도 undefined가 되지 않게 하려면 선언할 때 =
를 사용해 기본값 (default value)을 설정해주면 된다.
function showMessage(from, text = "no text given") {
alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given
매개변수 기본값을 설정할 수 있는 또 다른 방법
function showMessage(text) {
// ...
if (text === undefined) { // 매개변수가 생략되었다면
text = '빈 문자열';
}
alert(text);
}
showMessage(); // 빈 문자열
||
사용// 매개변수가 생략되었거나 빈 문자열("")이 넘어오면 변수에 '빈 문자열'이 할당됩니다.
function showMessage(text) {
text = text || '빈 문자열';
...
}
// 매개변수 'count'가 `undefined` 또는 `null`이면 'unknown'을 출력해주는 함수
function showCount(count) {
alert(count ?? "unknown");
}
showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown
반환값(return value): 함수를 호출했을 때 함수를 호출한 그곳에 반환하는 특정 값
지시자 return은 함수 내 어디에서 사용 가능.
function checkAge(age) {
if (age >= 18) {
return true;
} else {
return confirm('보호자의 동의를 받으셨나요?');
}
}
let age = prompt('나이를 알려주세요', 18);
if ( checkAge(age) ) {
alert( '접속 허용' );
} else {
alert( '접속 차단' );
}
주요 함수 접두어만 알아두자.
함수는 동작 하나만을 담당하는 것이 좋다.
이름만 보고 어떤 동작을 할 수 있는지 알 수 있는 코드: 자기 설명적 코드 (self-describing)
"show..." - 대개 무언가를 보여주는 함수.
"get…" – 값을 반환함
"calc…" – 무언가를 계산함
"create…" – 무언가를 생성함
"check…" – 무언가를 확인하고 불린값을 반환함
자바스크립트는 함수를 특별한 종류의 값으로 취급.
함수는 위처럼 선언하는 방식(function declaration)이 아니라 함수 표현식 (function expression)을 사용해서 함수를 만들 수 있다.
let sayHi = function() {
alert( "Hello" );
};
alert( sayHi ); // 함수 코드가 보임
함수는 값이기 때문에 변수에 할당할 수 있다.
함수를 만들고 그 함수를 변수 sayHi
에 할당한 것과 같은 상태이다.
자바스크립트는 괄호가 있어야많 함수가 호출된다.
괄호가 없을 때에는 함수 소스코드가 문자형으로 바뀌어 출력된다.
변수를 복사해 다른 변수에 할당하는 것처럼 함수를 복사해 다른 변수에 할당할 수도 있다.
function sayHi() { // (1) 함수 생성
alert( "Hello" );
}
let func = sayHi; // (2) 함수 복사
func(); // Hello // (3) 복사한 함수를 실행(정상적으로 실행됩니다)!
sayHi(); // Hello // 본래 함수도 정상적으로 실행됩니다.
함수 표현식에 쓰인 세미 콜론은 구문의 끝이기 때문에 붙게 된다.
함수를 함수의 인수로 전달하고, 필요하다면 인수로 전달한 그 함수를 나중에 호출(called back)하는 것이 콜백 함수이다.
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
function showOk() {
alert( "동의하셨습니다." );
}
function showCancel() {
alert( "취소 버튼을 누르셨습니다." );
}
// 사용법: 함수 showOk와 showCancel가 ask 함수의 인수로 전달됨
ask("동의하십니까?", showOk, showCancel);
함수 ask의 인수, showOk와 showCancel은 콜백 함수 또는 콜백이라고 부른다.
function ask(question, yes, no) {
if (confirm(question)) yes()
else no();
}
ask(
"동의하십니까?",
function() { alert("동의하셨습니다."); },
function() { alert("취소 버튼을 누르셨습니다."); }
);
이렇게 더 간단하게 표현할 수 있게 되는데, ask(...) 안에 선언된 함수는 이름 없이 선언되었기 때문에 익명 함수(anonymous function) 라고 부른다.
익명함수는 ask 바깥쪽에서 접근할 수 없다.
함수는 동작을 나타내는 값이다.
문자열이나 숫자 등의 일반적인 값들은 데이터를 나타낸다.
동작을 대변하는 값인 함수를 변수 간 전달, 동작이 필요할 때 이 값을 실행할 수 있다.
// 함수 선언문
function sum(a, b) {
return a + b;
}
// 함수 표현식
let sum = function(a, b) {
return a + b;
};
// 함수 선언문, 어디서든 접근 가능
sayHi("John"); // Hello, John
function sayHi(name) {
alert( `Hello, ${name}` );
}
// 함수 표현식, 선언되기 전에 접근 불가능
sayHi("John"); // error!
let sayHi = function(name) { // (*) 마술은 일어나지 않습니다.
alert( `Hello, ${name}` );
};
let age = 16; // 16을 저장했다 가정합시다.
if (age < 18) {
welcome(); // \ (실행)
// |
function welcome() { // |
alert("안녕!"); // | 함수 선언문은 함수가 선언된 블록 내
} // | 어디에서든 유효합니다
// |
welcome(); // / (실행)
} else {
function welcome() {
alert("안녕하세요!");
}
}
// 여기는 중괄호 밖이기 때문에
// 중괄호 안에서 선언한 함수 선언문은 호출할 수 없습니다.
그러나 함수 표현식을 사용하면 블록 밖에서도 접근할 수 있다.
let age = prompt("나이를 알려주세요.", 18);
let welcome;
if (age < 18) {
welcome = function() {
alert("안녕!");
};
} else {
welcome = function() {
alert("안녕하세요!");
};
}
welcome(); // 제대로 동작합니다.
let func = (arg1, arg2, ...argN) => expression
// 이 함수의 축약 버전
let func = function(arg1, arg2, ...argN) {
return expression;
};
이렇게 코드를 작성하면 인자 arg1..argN를 받는 함수 func이 만들어진다.
함수 func는 화살표(=>) 우측의 표현식(expression)을 평가하고, 평가 결과를 반환.
인수가 하나밖에 없으면 인수를 감싸는 괄호를 생략할 수 있다.
let double = n => n * 2;
// let double = function(n) { return n * 2 }과 거의 동일합니다.
alert( double(3) ); // 6
인수가 하나도 없을 땐 괄호를 비워놓을 수 있다. 이때는 괄호 생략 불가능.
let sayHi = () => alert("안녕하세요!");
sayHi();
평가해야 할 표현식이나 구문이 여러 개인 함수일 때는 중괄호 안에 평가해야 할 코드를 넣는다.
그리고 return 지시자를 사용해 명시적으로 결괏값을 반환해주어야 한다.
let sum = (a, b) => { // 중괄호는 본문 여러 줄로 구성되어 있음을 알려줍니다.
let result = a + b;
return result; // 중괄호를 사용했다면, return 지시자로 결괏값을 반환해주어야 합니다.
};
alert( sum(1, 2) ); // 3
"화살표 함수는 본문이 한 줄인 함수를 작성할 때 유용합니다. 본문이 한 줄이 아니라면 다른 방법으로 화살표 함수를 작성해야 합니다."
"중괄호 없이 작성: (...args) => expression – 화살표 오른쪽에 표현식을 둡니다. 함수는 이 표현식을 평가하고, 평가 결과를 반환합니다.
중괄호와 함께 작성: (...args) => { body } – 본문이 여러 줄로 구성되었다면 중괄호를 사용해야 합니다. 다만, 이 경우는 반드시 return 지시자를 사용해 반환 값을 명기해 주어야 합니다."