[TIL] 자바스크립트 study-01
1.자바스크립트 기본
1-1. Hello World
<script> 태그를 이용하면 자바스크립트 프로그램을 HTML 문서 대부분의 위치에 삽입할 수 있습니다.
<!DOCTYPE HTML>
<html>
<body>
<p>스크립트 전</p>
<script>
alert( 'Hello, world!' );
</script>
<p>스크립트 후</p>
</body>
</html>
HTML4에선 스크립트에 type을 명시하는 것이 필수였습니다. 따라서 type="text/javascript" 속성이 붙은 스크립트를 어렵지 않게 찾을 수 있었습니다. 이젠 타입 명시가 필수가 아닙니다.
외부스크립트
<script src="/path/to/script.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
주의:
HTML 안에 직접 스크립트를 작성하는 방식은 대개 스크립트가 아주 간단할 때만 사용
스크립트가 길어지면 별개의 분리된 파일로 만들어 저장하는 것이 좋다
스크립트를 별도의 파일에 작성하면 브라우저가 스크립트를 다운받아 캐시(cache)에 저장하기 때문에, 성능상의 이점 존재
여러 페이지에서 동일한 스크립트를 사용하는 경우, 브라우저는 페이지가 바뀔 때마다 스크립트를 새로 다운받지 않고 캐시로부터 스크립트를 가져와 사용. 스크립트 파일을 한 번만 다운받으면 이를 통해 트래픽이 절약되고 웹 페이지의 실제 속도가 빨라진다
2.코드구조
처음으로 배울 것은 코드 블록을 만드는 방법
2-1. 문
문(statement)은 어떤 작업을 수행하는 문법 구조(syntax structure)와 명령어(command)를 의미
앞서 ‘Hello, world!’ 메시지를 보여주는 alert('Hello, world!') 문을 확인
코드엔 원하는 만큼 문을 작성 이때, 서로 다른 문은 세미콜론으로 구분
아래 코드는 'Hello World’를 두 개의 alert 문으로 나눈 예시
alert('Hello');
alert('World');
2-2. 세미콜론
자바스크립트는 줄 바꿈이 있으면 이를 ‘암시적’ 세미콜론으로 해석
이런 동작 방식을 세미콜론 자동 삽입(automatic semicolon insertion)이라 부른다.
alert(3 +
1
+ 2);
세미콜론 자동 삽입이 일어나지 않았기 때문에 6이 출력
어떤 줄이 "+" 로 끝나면, 그 줄은 '불완전한 표현식’ 이므로 줄마다 세미콜론이 필요하지않음
반면, 세미콜론이 정말로 필요하지만 자바스크립트가 이를 추정하지 ‘못하는’ 상황도 존재
이런 상황에서 발생하는 에러는 찾거나 고치기가 상당히 어렵다
alert("에러가 발생합니다.")
[1, 2].forEach(alert)
이유는 [1,2] 대괄호 앞에는 세미콜론이 있다고 가정하지 않기 때문
따라서 세미콜론 자동 삽입이 일어나지 않고 첫 번째 예제는 단일 문으로 처리
2-2 주석
시간이 흐르며 자바스크립트 프로그램은 더욱더 복잡해짐
이로 인해 무슨 일이 왜 벌어지고 있는지를 설명해주는 주석(comment) 의 필요성이 요구됨
주석은 스크립트의 어느 곳에나 작성할 수 있다.
자바스크립트 엔진은 주석을 무시하기 때문에 주석의 위치는 실행에 영향을 주지 않습니다.
한 줄짜리 주석은 두 개의 슬래시 //
// 이 주석은 한 줄을 다 차지합니다.
alert('Hello');
alert('World'); // 이 주석은 문 다음 이어집니다.
여러 줄의 주석은 슬래시와 별표 /*로 시작해 별표와 슬래시 */로 끝난다.
/* 두 줄짜리 주석 예제
이것은 여러 줄의 주석입니다.
*/
alert('Hello');
alert('World');
주석 /* … */ 안에 코드가 들어가도 이 코드는 실행되지 않는다.
이를 이용하면 코드 일부를 일시적으로 비활성화할 수 있음
/* 코드 주석 처리하기
alert('Hello');
*/
alert('World');
중첩 주석은 지원하지 않습니다.
/*
/* 중첩 주석 ?!? */
*/
alert( 'World' );
3. alert, prompt, confirm 을 이용한 상호작용
브라우저를 데모 환경으로 사용 중이므로 브라우저 환경에서 사용되는
최소한의 사용자 인터페이스 기능인 alert, prompt, confirm을 알아보자.
3-1. alert
이 함수가 실행되면 사용자가 ‘확인(OK)’ 버튼을 누를 때까지 메시지를 보여주는 창이 계속 떠있게 된다.
alert("Hello");
3-2. prompt
브라우저에서 제공하는 prompt 함수는 두 개의 인수를 받습니다.
result = prompt(title, [default]);
title사용자에게 보여줄 문자열
default입력 필드의 초깃값(선택값)
예시는 다음과같다.
let age = prompt('나이를 입력해주세요.', 100);
alert(`당신의 나이는 ${age}살 입니다.`); // 당신의 나이는 100살입니다.
let test = prompt("Test", ''); // <-- IE 사용자를 위한 매개변수 처리
4.주석
한 줄짜리 주석은 //로, 여러 줄의 주석은 /* ... */로 시작합니다.
주석(comment)은 어떻게 코드가 동작하는지, 왜 코드가 동작하는지를 설명하는 데 쓰임.
주석을 작성하는 게 쉬워 보일 수 있는데, 그렇지않다
4-1. 좋지않은 주석
// 이 코드는 (...)과 (...)을 수행합니다
// A라는 개발자가 이 기능에 대해 알고 있으며...
very;
complex;
code;
‘설명이 담긴(explanatory)’ 주석이 많아선 안된다고한다. 주석 없이 코드 자체만으로 코드가 무슨 일을 하는지 쉽게 이해할 수 있어야 함.
4-2. 좋은 주석
설명이 담긴 주석은 대개 좋지 않음. 그럼 좋은 주석이란 무엇?
4-2-1. 아키텍처를 설명하는 주석
고차원 수준 컴포넌트 개요, 컴포넌트 간 상호작용에 대한 설명, 상황에 따른 제어 흐름 등은 주석
4-2-2. 함수 용례와 매개변수 정보를 담고 있는 주석
JSDoc이라는 특별한 문법을 사용하면 함수에 관한 문서를 쉽게 작성할 수 있다.
여기엔 함수 용례, 매개변수, 반환 값 정보가 들어감
다음과같은 예시
/**
* x를 n번 곱한 수를 반환함
*
* @param {number} x 거듭제곱할 숫자
* @param {number} n 곱할 횟수, 반드시 자연수여야 함
* @return {number} x의 n 거듭제곱을 반환함
*/
function pow(x, n) {
...
}
4-2-3. 왜 이런 방법으로 문제를 해결했는지를 설명하는 주석
문제 해결 방법이 여러 가지인데 왜 하필이면 이 방법을 택했는지 의문이 들 때가 달아주는게 좋다.
왜 이런 방법을 써서 문제를 해결했는지 알려주는 주석이 없으면 다음과 같은 일이 발생할 수 있음
- 당신(혹은 동료)은 작성된 후 시간이 꽤 흐른 코드를 열어봅니다. 그리고 그 코드에서 선택한 방식이 ‘가장 좋은 방식은 아니란 걸’ 알아냅니다.
- "그때는 내가 멍청했구나. 하지만 지금은 더 똑똑해졌지"라고 생각하며, 이전보단 ‘더 명확하고 올바른’ 방법으로 코드를 개선합니다.
- 코드를 개선하려는 시도까지는 좋았습니다. 하지만 리팩토링 과정에서 '더 명확’하다고 생각했던 방법을 적용하면 문제가 발생한다는 걸 알아냅니다. 이미 시도해봤던 방법이기 때문에 왜 이 방법이 먹히지 않는지 희미하게 기억이 떠오릅니다. 새로 작성한 코드를 되돌렸지만, 시간이 낭비되었습니다.
해결 방법을 담고 있는 주석은 아주 중요한 역할을 합니다. 이전에 했던 실수를 방지하는 안내판 역할을 하기 때문
5. 변수와 상수
5-1. 변수
변수(variable)는 데이터를 저장할 때 쓰이는 ‘이름이 붙은 저장소’
let user = 'John';
let age = 25;
let message = 'Hello';
let은 상자와 같아서 상자안에 내용물을 넣다가 뺐다가 할 수 있다.
변수를 두 번 선언하면 에러가 발생
5-2. 변수 명명 규칙
let 1a; // 변수명은 숫자로 시작해선 안 됩니다.
let my-name; // 하이픈 '-'은 변수명에 올 수 없습니다.
여러 단어를 조합하여 변수명을 만들 땐 카멜 표기법(camelCase)이 흔히 사용
5-3. 상수
변화하지 않는 변수를 선언할 땐, let 대신 const를 사용합니다.
const myBirthday = '18.04.1982';
myBirthday = '01.01.2001'; // error, can't reassign the constant!
5-4. 대문자상수
기억하기 힘든 값을 변수에 할당해 별칭으로 사용하는 것은 널리 사용되는 관습이라고 함.
이런 상수는 대문자와 밑줄로 구성된 이름으로 명명
const COLOR_RED = "#F00";
const COLOR_GREEN = "#0F0";
const COLOR_BLUE = "#00F";
const COLOR_ORANGE = "#FF7F00";
// 색상을 고르고 싶을 때 별칭을 사용할 수 있게 되었습니다.
let color = COLOR_ORANGE;
alert(color); // #FF7F00
6. 자료형
자바스크립트에서 값은 항상 문자열이나 숫자형 같은 특정한 자료형에 속함
- 숫자형 – 정수, 부동 소수점 숫자 등의 숫자를 나타낼 때 사용. 정수의 한계는 ±253
- Bigint – 길이 제약 없이 정수를 나타낼 수 있음
- 문자형 – 빈 문자열이나 글자들로 이뤄진 문자열을 나타낼 때 사용 단일 문자를 나타내는 별도의 자료형은 없음
- 불린형 – true, false를 나타낼 때 사용
- null – null 값만을 위한 독립 자료형. null은 알 수 없는 값을 나타냄
- undefined – undefined 값만을 위한 독립 자료형. undefined는 할당되지 않은 값
- 객체형 – 복잡한 데이터 구조를 표현할 때 사용
- 심볼형 – 객체의 고유 식별자를 만들 때 사용
typeof 연산자는 피연산자의 자료형을 알려줍니다.
- typeof S 또는 typeof(S) 형태로 사용합니다.
- 피연산자의 자료형을 문자열 형태로 반환
- null의 typeof 연산은 "object"인데, 이는 언어상 오류. null은 객체가 아님
let name = "Ilya";
// 표현식은 숫자 1
alert( `hello ${1}` ); // hello 1
// 표현식은 문자열 "name"
alert( `hello ${"name"}` ); // hello name
// 표현식 안에 변수가 들어가 있기 때문에, 이 변수가 평가되어 전체 문자열이 반환
alert( `hello ${name}` ); // hello Ilya
7. 형 변환
함수와 연산자에 전달되는 값은 대부분 적절한 자료형으로 자동 변환
이런 과정을 "형 변환(type conversion)"이라고 함.
alert가 전달받은 값의 자료형과 관계없이 이를 문자열로 자동 변환하여 보여주는 것이나, 수학 관련 연산자가 전달받은 값을 숫자로 변환하는 경우가 형 변환의 대표적인 예시
이 외에, 전달받은 값을 의도를 갖고 원하는 타입으로 변환(명시적 변환)해 주는 경우도 형 변환이라 함
문자형으로 변환 은 무언가를 출력할 때 주로 일어납니다.
String(value)을 사용하면 문자형으로 명시적 변환이 가능
숫자형으로 변환 은 수학 관련 연산시 주로 일어난다.
Number(value)로도 형 변환을 할 수 있음
숫자형으로의 변환은 다음 규칙을 따른다.
전달받은 값 형 변환 후
undefined NaN
null 0
true / false 1 / 0
string 전달받은 문자열을 “그대로” 읽되, 처음과 끝의 공백을 무시합니다. 문자열이 비어있다면 0이 되고, 오류 발생 시 NaN이 됩니다.
8. 기본연산자와 수학
기본 연산자를 시작으로 학교에선 다루지 않았던 자바스크립트에서만 제공하는 연산자에 대해 알아보자
8-1. 용어: ‘단항’, ‘이항’, ‘피연산자’
- 연산자(operand) 는 연산자가 연산을 수행하는 대상입니다. 5 * 2에는 왼쪽 피연산자 5와 오른쪽 피연산자 2, 총 두 개의 피연산자가 있습니다. '피연산자’는 '인수(argument)'라는 용어로 불리기도 합니다.
- 피연산자를 하나만 받는 연산자는 단항(unary) 연산자 라고 부릅니다. 피연산자의 부호를 뒤집는 단항 마이너스 연산자 -는 단항 연산자의 대표적인 예입니다.
let x = 1;
x = -x;
alert( x ); // -1, 단항 마이너스 연산자는 부호를 뒤집습니다.
- 두 개의 피 연산자를 받는 연산자는 이항 연산자라고 보른다. 마이너스 연산자는 아래와 같이 이항 연산자로 쓸 수도.
let x = 1, y = 3;
alert( y - x ); // 2, 이항 마이너스 연산자는 뺄셈을 해줍니다.
8-2. 할당연산자
= 는 연산자이기 때문에 흥미로운 함축성을 내포하고 있음
+와 -뿐만 아니라 = 역시 값을 반환
x = value을 호출하면 value가 x에 쓰여지고, 이에 더하여 value가 반환
할당 연산자의 이런 특징을 이용한 복잡한 표현식을 살펴보자
let x = 2 * 2 + 1;
alert( x ); // 5
8-3. 할당연산자 체이닝
let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
그런데 되도록이면 연산자를 체이닝 하는것 보다 가독성을 위해 아래와 같이 줄을 나눠 코드를 작성하길 권유
c = 2 + 2;
b = c;
a = c;
8-4. 증가 감소 연산자
숫자를 하나 늘리거나 줄이는 것은 자주 사용되는 연산. 자바스크립트에서는 이런 연산을 해주는 연산자를 제공
let counter = 2;
counter++; // counter = counter + 1과 동일하게 동작합니다. 하지만 식은 더 짧습니다.
alert( counter ); // 3
let counter = 2;
counter--; // counter = counter - 1과 동일하게 동작합니다. 하지만 식은 더 짧습니다.
alert( counter ); // 1
증가·감소 연산자는 변수에만 쓸 수 있습니다. 5++와 같이 값에 사용하려고 하면 에러가 발생합니다.
- counter++와 같이 피연산자 뒤에 올 때는, '후위형(postfix form)'이라고 부름
- ++counter와 같이 피연산자 앞에 올 때는, '전위형(prefix form)'이라고 부른다.
let counter = 1;
let a = ++counter; // (*)
alert(a); // 2
(*)로 표시한 줄의 전위형 ++counter는 counter를 증가시키고 새로운 값 2를 반환합니다. 따라서 alert는 2를 표시합니다.
이제 후위형을 살펴봅시다.
let counter = 1;
let a = counter++; // (*) ++counter를 counter++로 바꿈
alert(a); // 1
(*)로 표시한 줄의 후위형 counter++는 counter를 증가시키긴 하지만,
증가 전의 기존 값을 반환합니다. 따라서 alert는 1을 표시합니다.
9. 비교연산자
자바스크립트에서 기본 수학 연산은 아래와 같은 문법을 사용해 표현할 수 있다
- 보다 큼·작음: a > b, a < b
- 보다 크거나·작거나 같음: a >= b, a <= b
- 같음(동등): a == b. 등호 =가 두 개 연달아 오는 것에 유의 a = b와 같이 등호가 하나일 때는 할당을 의미
- 같지 않음(부등): 같지 않음을 나타내는 수학 기호 ≠는 자바스크립트에선 a != b로 나타냄. 할당연산자 = 앞에 느낌표 !를 붙여서 표시한다.
9-1. 불린형 반환
alert( 2 > 1 ); // true
alert( 2 == 1 ); // false
alert( 2 != 1 ); // true
let result = 5 > 4; // 비교 결과를 변수에 할당
alert( result ); // true
9-2. 문자열 비교
자바스크립트는 ‘사전’ 순으로 문자열을 비교합니다.
alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true
예시의 'Z' > 'A'는 위 알고리즘의 첫 번째 단계에서 비교 결과가 도출
반면, 문자열 'Glow'와 'Glee'는 복수의 문자로 이루어진 문자열이기 때문에, 아래와 같은 순서로 문자열 비교가 이뤄짐
- G는 G와 같다
- l은 l과 같다
- o는 e보다 크기 때문에 여기서 비교가 종료되고, o가 있는 첫 번째 문자열 'Glow'가 더 크다는 결론이 도출
9-3. 다른 형을 가진 값 간의 비교
alert( '2' > 1 ); // true, 문자열 '2'가 숫자 2로 변환된 후 비교가 진행됩니다.
alert( '01' == 1 ); // true, 문자열 '01'이 숫자 1로 변환된 후 비교가 진행됩니다.
불린값의 경우 true는 1, false는 0으로 변환된 후 비교가 이뤄집니다.
예시:
alert( true == 1 ); // true
alert( false == 0 ); // true
9-4. 일치 연산자
동등 연산자(equality operator) ==은 0과 false를 구별하지 못합니다.
alert( 0 == false ); // true
피연산자가 빈 문자열일 때도 같은 문제가 발생하죠.
alert( '' == false ); // true
- 비교 연산자는 불린값을 반환합니다.
- 문자열은 문자 단위로 비교되는데, 이때 비교 기준은 ‘사전’ 순입니다.
- 서로 다른 타입의 값을 비교할 땐 숫자형으로 형 변환이 이뤄지고 난 후 비교가 진행됩니다(일치 연산자는 제외).
- null과 undefined는 동등 비교(==) 시 서로 같지만 다른 값과는 같지 않습니다.
- null이나 undefined가 될 확률이 있는 변수가 > 또는 <의 피연산자로 올 때는 주의를 기울이시기 바랍니다. null, undefined 여부를 확인하는 코드를 따로 추가하는 습관을 들이길 권유합니다.
9. if문과 반복문
가장 중요한 내용으로 로직을 처리하는데 필요한 문법
9-1. if문
if(...)문은 괄호 안에 들어가는 조건을 평가하는데, 그 결과가 true이면 코드 블록이 실행
예시:
let year = prompt('ECMAScript-2015 명세는 몇 년도에 출판되었을까요?', '');
if (year == 2015) alert( '정답입니다!' );
위 예시에선 조건(year == 2015)이 간단한 경우만 다뤘는데, 조건문은 더 복잡할 수도
조건이 true일 때 복수의 문을 실행하고 싶다면 중괄호로 코드 블록을 감싸야한다.
if (year == 2015) {
alert( "정답입니다!" );
alert( "아주 똑똑하시네요!" );
}
9-2.불린형으로의 변환
if (0) { // 0은 falsy입니다.
...
}
아래 예시의 코드 블록은 항상 실행됩니다.
if (1) { // 1은 truthy입니다.
...
}
9-3.조건부 연산자
let accessAllowed;
let age = prompt('나이를 입력해 주세요.', '');
if (age > 18) {
accessAllowed = true;
} else {
accessAllowed = false;
}
alert(accessAllowed);
9-4. 삼항 연산자
// 연산자 우선순위 규칙에 따라, 비교 연산 'age > 18'이 먼저 실행됩니다.
// (조건문을 괄호로 감쌀 필요가 없습니다.)
let accessAllowed = age > 18 ? true : false;
개발자 입장에선 if문을 사용할 때 보다 코드 길이가 짧아진다는 점 때문에 물음표?를 if 대용으로 쓰는 게 매력적일 순 있습니다. 하지만 이렇게 코드를 작성하면 가독성이 떨어집니다.
let company = prompt('자바스크립트는 어떤 회사가 만들었을까요?', '');
(company == 'Netscape') ?
alert('정답입니다!') : alert('오답입니다!');
let company = prompt('자바스크립트는 어떤 회사가 만들었을까요?', '');
if (company == 'Netscape') {
alert('정답입니다!');
} else {
alert('오답입니다!');
}
9-5. 'while'반복문
while (condition) {
// 코드
// '반복문 본문(body)'이라 불림
}
while (condition) {
// 코드
// '반복문 본문(body)'이라 불림
}
condition(조건)이 truthy 이면 반복문 본문의 코드가 실행됩니다.
아래 반복문은 조건 i < 3을 만족할 동안 i를 출력해줍니다.
let i = 0;
while (i < 3) { // 0, 1, 2가 출력됩니다.
alert( i );
i++;
}
9-6. 'do-while'반복문
do..while 문법을 사용하면 condition을 반복문 본문 아래로 옮길 수 있다.
do {
// 반복문 본문
} while (condition);
이때 본문이 먼저 실행되고, 조건을 확인한 후 조건이 truthy인 동안엔 본문이 계속 실행됩니다.
예시:
let i = 0;
do {
alert( i );
i++;
} while (i < 3);
9-7. 'for'반복문
for 반복문은 while 반복문보다는 복잡하지만 가장 많이 쓰이는 반복문
for (begin; condition; step) {
// ... 반복문 본문 ...
}
for문을 구성하는 각 요소가 무엇을 의미하는지 알아보자. 아래 반복문을 실행하면 i가 0부터 3이 될 때까지(단, 3은 포함하지 않음) alert(i)가 호출
for (let i = 0; i < 3; i++) { // 0, 1, 2가 출력됩니다.
alert(i);
}
9-8 다음반복으로 넘어가기
continue는 전체 반복문을 멈추지 않습니다.
대신에 현재 실행 중인 이터레이션을 멈추고 반복문이 다음 이터레이션을 강제로 실행시키도록 한다.(조건을 통과할 때).
continue는 현재 반복을 종료시키고 다음 반복으로 넘어가고 싶을 때 사용할 수 있다.
아래 반복문은 continue를 사용해 홀수만 출력
for (let i = 0; i < 10; i++) {
// 조건이 참이라면 남아있는 본문은 실행되지 않습니다.
if (i % 2 == 0) continue;
alert(i); // 1, 3, 5, 7, 9가 차례대로 출력됨
}
i가 짝수이면 continue가 본문 실행을 중단시키고 다음 이터레이션이 실행(i가 하나 증가하고, 다음 반복이 실행됨). 따라서 alert 함수는 인수가 홀수일 때만 호출
for (let i = 0; i < 10; i++) {
if (i % 2) {
alert( i );
}
}
기술적인 관점에서 봤을 때, 이 예시는 위쪽에 있는 예시와 동일
continue를 사용하는 대신 코드를 if 블록으로 감싼 점만 다르다. 그런데 이렇게 코드를 작성하면 부작용으로 중첩 레벨(대괄호 안의 alert 호출)이 하나 더 늘어나게됨. if 안의 코드가 길어진다면 전체 가독성이 떨어질 수 있음
요약
지금까지 세 종류의 반복문에 대해 살펴보았다.
- while – 각 반복이 시작하기 전에 조건을 확인
- do..while – 각 반복이 끝난 후에 조건을 확인
- for (;;) – 각 반복이 시작하기 전에 조건을 확인 추가 세팅을 할 수 있음
‘무한’ 반복문은 보통 while(true)를 써서 만듦.
무한 반복문은 여타 반복문과 마찬가지로 break 지시자를 사용해 멈출 수 있다.
현재 실행 중인 반복에서 더는 무언가를 하지 않고 다음 반복으로 넘어가고 싶다면 continue 지시자를 사용할 수 있다.
반복문 앞에 레이블을 붙이고, break/continue에 이 레이블을 함께 사용할 수 있다.
레이블은 중첩 반복문을 빠져나와 바깥의 반복문으로 갈 수 있게 해주는 유일한 방법