if (true) alert( 'true' );
if (true) {
alert( 'true' );
}
if (…) 문은 괄호 안의 표현식을 평가하고 그 결과를 불린값으로 변환
if (0) { // 0은 falsy
...
}
if (1) { // 1은 truthy
...
}
'물음표(question mark) 연산자’라고도 불리는 '조건부(conditional) 연산자’를 사용하면 더 짧고 간결하게 변형할 수 있음
let result = condition ? value1 : value2;
평가 대상인 condition이 truthy라면 value1이, 그렇지 않으면 value2가 반환
물음표?를 if 대용으로 쓰는 경우는 지양
||(OR), &&(AND), !(NOT)
인수 중 하나라도 true이면 true를 반환하고, 그렇지 않으면 false를 반환
alert( true || true ); // true
alert( false || true ); // true
alert( true || false ); // true
alert( false || false ); // false
🚨 왼쪽부터 피연산자를 불린형으로 변환 후 그 값이 true이면 연산을 멈추고 해당 피연산자의 변환 전 원래 값 을 반환.
🚨 피연산자 모두를 평가한 경우(모든 피연산자가 false로 평가되는 경우)엔 마지막 피연산자를 반환
1. 변수 또는 표현식으로 구성된 목록에서 첫 번째 truthy 얻기
let firstName = "";
let lastName = "";
let nickName = "바이올렛";
alert( firstName || lastName || nickName || "익명"); // 바이올렛
2. 단락 평가
truthy를 만나면 나머지 값들은 건드리지 않은 채 평가를 멈춤
true || alert("not printed"); // 출력 X
false || alert("printed"); // 출력 O
alert( true && true ); // true
alert( false && true ); // false
alert( true && false ); // false
alert( false && false ); // false
🚨 왼쪽부터 피연산자를 불린형으로 변환 후 값이 false이면 평가를 멈추고 해당 피연산자의 변환 전 원래 값 을 반환
🚨 피연산자 모두가 평가되는 경우(모든 피연산자가 true로 평가되는 경우)엔 마지막 피연산자가 반환
AND 연산자 &&의 우선순위는 OR 연산자 ||보다 높음
따라서a && b || c && d
는(a && b) || (c && d)
와 동일하게 동작합니다.
NOT을 두 개 연달아 사용(!!)하면 값을 불린형으로 변환
요약
null 병합 연산자 ??를 사용하면 피연산자 중 ‘값이 할당된’ 변수를 빠르게 찾을 수 있습니다.
??는 변수에 기본값을 할당하는 용도로 사용할 수 있습니다.// height가 null이나 undefined인 경우, 100을 할당 height = height ?? 100;
??의 연산자 우선순위는 대다수의 연산자보다 낮고 ?와 = 보다는 높습니다.
괄호 없이 ??를 ||나 &&와 함께 사용하는 것은 금지되어있습니다.
null 병합 연산자(nullish coalescing operator) ??를 사용하면 짧은 문법으로 여러 피연산자 중 그 값이 ‘확정되어있는’ 변수를 찾을 수 있음
a ?? b
x = (a !== null && a !== undefined) ? a : b
;즉, a가 확정되어있는 변수면 a 아니면 b
let firstName = null;
let lastName = null;
let nickName = "바이올렛";
// null이나 undefined가 아닌 첫 번째 피연산자
alert(firstName ?? lastName ?? nickName ?? "익명의 사용자"); // 바이올렛
null과 undefined, 숫자 0을 구분 지어 다뤄야 할 때 이 차이점은 매우 중요한 역할
let height = 0;
alert(height || 100); // 100
alert(height ?? 100); // 0
요약
while – 각 반복이 시작하기 전에 조건을 확인합니다.
do..while – 각 반복이 끝난 후에 조건을 확인합니다.
for (;;) – 각 반복이 시작하기 전에 조건을 확인합니다. 추가 세팅을 할 수 있습니다.
‘무한’ 반복문은 보통 while(true)를 써서 만듭니다. 무한 반복문은 여타 반복문과 마찬가지로 break 지시자를 사용해 멈출 수 있습니다.
현재 실행 중인 반복에서 더는 무언가를 하지 않고 다음 반복으로 넘어가고 싶다면 continue 지시자를 사용할 수 있습니다.
반복문 앞에 레이블을 붙이고, break/continue에 이 레이블을 함께 사용할 수 있습니다. 레이블은 중첩 반복문을 빠져나와 바깥의 반복문으로 갈 수 있게 해주는 유일한 방법입니다.
while (condition) {
// 코드
// '반복문 본문(body)'
}
condition(조건)
이 truthy 이면 반복문 본문의 코드가 실행
do {
// 반복문 본문
} while (condition);
for (begin; condition; step) {
// ... 반복문 본문 ...
}
for (let i = 0; i < 3; i++) { // 0, 1, 2
alert(i);
}
begin
이 한 차례 실행된 이후에, condition
확인과 body
, step
이 계속해서 반복 실행begin
또는 step
생략 가능
break나 continue 같은 지시자는 삼항 연산자에 사용이 불가함
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('완료!');
continue
지시자를 레이블과 함께 사용하는 것도 가능. 두 가지를 같이 사용하면 레이블이 붙은 반복문의 다음 이터레이션이 실행break와 continue는 반복문 안에서만 사용할 수 있고, 레이블은 반드시 break이나 continue 지시자 위에 있어야 함
switch(x) {
case 'value1': // if (x === 'value1')
...
[break]
case 'value2': // if (x === 'value2')
...
[break]
default:
...
[break]
}
🚨 case문 안에 break문이 없으면 조건에 부합하는지 여부를 따지지 않고 이어지는 case문을 실행
let a = 3;
switch (a) {
case 4:
alert('계산이 맞습니다!');
break;
case 3: // (*) 두 case문을 묶음
case 5:
alert('계산이 틀립니다!');
alert("수학 수업을 다시 들어보는걸 권유 드립니다.");
break;
default:
alert('계산 결과가 이상하네요.');
}
요약
함수 선언 방식으로 함수를 만들 수 있습니다.function 함수이름(복수의, 매개변수는, 콤마로, 구분) { /* 함수 본문 */ }
함수에 전달된 매개변수는 복사된 후 함수의 지역변수가 됩니다.
함수는 외부 변수에 접근할 수 있습니다. 하지만 함수 바깥에서 함수 내부의 지역변수에 접근하는 건 불가능합니다.
함수는 값을 반환할 수 있습니다. 값을 반환하지 않는 경우는 반환 값이 undefined가 됩니다.
깔끔하고 이해하기 쉬운 코드를 작성하려면 함수 내부에서 외부 변수를 사용하는 방법 대신 지역 변수와 매개변수를 활용하는 게 좋습니다.
개발자는 매개변수를 받아서 그 변수를 가지고 반환 값을 만들어 내는 함수를 더 쉽게 이해할 수 있습니다. 매개변수 없이 함수 내부에서 외부 변수를 수정해 반환 값을 만들어 내는 함수는 쉽게 이해하기 힘듭니다.
함수 이름을 지을 땐 아래와 같은 규칙을 따르는 것이 좋습니다.
함수 이름은 함수가 어떤 동작을 하는지 설명할 수 있어야 합니다. 이렇게 이름을 지으면 함수 호출 코드만 보아도 해당 함수가 무엇을 하고 어떤 값을 반환할지 바로 알 수 있습니다.
함수는 동작을 수행하기 때문에 이름이 주로 동사입니다.
create…, show…, get…, check… 등의 잘 알려진 접두어를 사용해 이름을 지을 수 있습니다. 접두어를 사용하면 함수 이름만 보고도 해당 함수가 어떤 동작을 하는지 파악할 수 있습니다.
function name(parameters) {
...함수 본문...
}
name(); // 함수 호출
Argument | 인수
함수를 호출할 때, 사용되는 값Parameter | 인자 | 매개변수
함수를 정의할 때, 외부로부터 받아들이는 임의의 값function name(parameter) { ...함수 본문... } name(argument)
function showMessage(from, text = "no text given") {
alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given
function showMessage2(from, text = anotherFunction()) {
// anotherFunction()은 text값이 없을 때만 호출됨
// anotherFunction()의 반환 값이 text의 값이 됨
}
function showMessage(text) {
if (text === undefined) {
text = '빈 문자열';
}
...
}
function showMessage2(text) {
text = text || '빈 문자열';
...
}
function showCount(count) {
alert(count ?? "unknown");
}
🚨
return
과 값 사이에 줄을 삽입하면return;
으로 인식되어undefined
가 반환
"show" – 무언가를 보여줌
"get…" – 값을 반환함
"calc…" – 무언가를 계산함
"create…" – 무언가를 생성함
"check…" – 무언가를 확인하고 불린값을 반환함
함수는 동작 하나만 담당
그 이외의 동작은 수행해선 안됨
이름만 보고도 어떤 동작을 하는지 알 수 있는 코드를 자기 설명적(self-describing) 코드라고 함
요약
함수는 값입니다. 따라서 함수도 값처럼 할당, 복사, 선언할 수 있습니다.
“함수 선언(문)” 방식으로 함수를 생성하면, 함수가 독립된 구문 형태로 존재하게 됩니다.
“함수 표현식” 방식으로 함수를 생성하면, 함수가 표현식의 일부로 존재하게 됩니다.
함수 선언문은 코드 블록이 실행되기도 전에 처리됩니다. 따라서 블록 내 어디서든 활용 가능합니다.
함수 표현식은 실행 흐름이 표현식에 다다랐을 때 만들어집니다.
함수를 선언해야 한다면 함수가 선언되기 이전에도 함수를 활용할 수 있기 때문에, 함수 선언문 방식을 따르는 게 좋습니다. 함수 선언 방식은 코드를 유연하게 구성할 수 있도록 해주고, 가독성도 좋습니다.
함수 표현식은 함수 선언문을 사용하는게 부적절할 때에 사용하는 것이 좋습니다.
// 함수 선언
function sayHi() {
alert( "Hello" );
}
// 함수 표현식
let sayHi = function() {
alert( "Hello" );
};
function sayHi() {
alert( "Hello" );
}
alert( sayHi ); // 함수 코드가 보임
function sayHi() {
alert( "Hello" );
}
alert( sayHi() ); // Hello, undefined
// 함수 내부에서 'Hello'를 alert하고,
// sayHi()의 return 값이 없기 때문에 undefined를 alert
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();
}
ask(
"동의하십니까?",
function() { alert("동의하셨습니다."); },
function() { alert("취소 버튼을 누르셨습니다."); }
);
함수 표현식은 실제 실행 흐름이 해당 함수에 도달했을 때 함수를 생성. 따라서 실행 흐름이 함수에 도달했을 때부터 해당 함수를 사용할 수 있음.
함수 선언문은 함수 선언문이 정의되기 전에도 호출할 수 있음. 따라서 전역 함수 선언문은 스크립트 어디에 있느냐에 상관없이 어디에서든 사용할 수 있음
엄격 모드에서 함수 선언문이 코드 블록 내에 위치하면 해당 함수는 블록 내 어디서든 접근할 수 있음. 하지만 블록 밖에서는 함수에 접근하지 못함
조건에 따라 함수를 선언해야 한다면 함수 표현식을 사용
요약
화살표 함수는 본문이 한 줄인 함수를 작성할 때 유용합니다. 본문이 한 줄이 아니라면 다른 방법으로 화살표 함수를 작성해야 합니다.
중괄호 없이 작성: (...args) => expression – 화살표 오른쪽에 표현식을 둡니다. 함수는 이 표현식을 평가하고, 평가 결과를 반환합니다.
중괄호와 함께 작성: (...args) => { body } – 본문이 여러 줄로 구성되었다면 중괄호를 사용해야 합니다. 다만, 이 경우는 반드시 return 지시자를 사용해 반환 값을 명기해 주어야 합니다.
// 기존 함수
let func = function(arg1, arg2, ...argN) {
return expression;
};
// 화살표 함수
let func = (arg1, arg2, ...argN) => expression
인수가 하나밖에 없다면 인수를 감싸는 괄호를 생략
let double = n => n * 2;
인수가 하나도 없을 땐 괄호를 비워놓음. 다만, 이 때 괄호는 생략할 수 없음
let sayHi = () => alert("안녕하세요!");
let sum = (a, b) => { // 중괄호는 본문 여러 줄로 구성되어 있음을 알림
let result = a + b;
return result; // 중괄호를 사용했다면, return 지시자로 결괏값을 반환해야 함
};
[]
의 앞'use strict'
let
const
– 한 번 값을 할당하면 더는 값을 바꿀 수 없는 상수를 정의var
– 과거에 쓰이던 키워드로 자세한 내용은 추후에 다룰 예정
typeof
연산자는 값의 자료형을 반환
typeof
의 예외 사항 두가지
1.typeof null == "object" // 언어 자체의 오류
2.typeof function(){} == "function" // 함수는 특별하게 취급
prompt(question, [default])
confirm(question)
alert(message)
*
+
-
/
와 나머지 연산자 %
, 거듭제곱 연산자 **
a = b
형태의 할당 연산자와 a *= 2
형태의 복합 할당 연산자
32비트 정수로 변환하여 이진 연산을 수행
cond ? resultA : resultB
AND 연산자 &&
와 OR 연산자 ||
은 단락 평가를 수행하고, 평가가 멈춘 시점의 값을 반환(꼭 true나 false일 필요는 없습니다).
NOT 연산자 !는피연산자의 자료형을 불린형으로 바꾼 후 그 역을 반환
??는 피연산자 중 실제 값이 정의된 피연산자를 찾는 데 쓰임
a가 null이나 undefined가 아니면 a ?? b
의 평가 결과는 a이고,
a가 null이나 undefined이면 a ?? b
의 평가 결과는 b가 됨
==
동등 연산자는 형이 다른 값끼리 비교할 때 피연산자의 자료형을 숫자형으로 바꾼 후 비교
< > <= >=
도 마찬가지
일치 연산자 ===
는 피연산자의 형을 변환하지 않고 비교
while
, do-while
, for
while (condition) {
...
}
do {
...
} while (condition);
for(let i = 0; i < 10; i++) {
...
}
지시자 break
나 continue
는 반복문 전체나 현재 실행 중인 반복을 빠져나가는 데 사용
레이블
은 중첩 반복문을 빠져나갈 때 사용
'switch’문은 조건을 확인할 때 내부적으로 일치 연산자 ===
를 사용해 비교를 진행
let age = prompt('나이를 알려주세요.', 18);
switch (age) {
case 18:
alert("Won't work"); // prompt 함수는 항상 문자열을 반환하므로, 이 case문엔 절대 도달할 수 없습니다.
break;
case "18":
alert("낭랑 18세이시군요!");
break;
default:
alert("어떤 case문에도 해당하지 않습니다.");
}