기본적으로 JS는 브라우저 환경에서만 사용할 수 있다.
하지만 Node.js 런타임을 이용해 브라우저 외에서 실행할 수 있으며, 그 중 ijavascript
패키지를 설치하면 주피터 노트북에서 JS 커널을 통해 파이썬 처럼 사용할 수 있게 된다.
npm install -g ijavascript
을 통해서 설치할 수 있다.
-g
옵션은 ijavascript를 global로 설치하는 옵션으로, 다른 모든 환경에 설치가 이루어진다.
설치한 환경에서 ijsinstall
명령어를 실행해주어 설치한다.
한 번 실행한 이후에는 주피터 노트북에서 Node.js 커널을 선택할 수 있다.
JS를 사용하는 목적은 CPU, RAM, 보조기억장치 자원을 활용하기 위해서이다.
이를 통해 웹브라우저에서 새로 고침 없이 동적으로 이벤트를 처리하고 웹페이지의 내용을 변경할 수 있다.
JS는 ES5, ES6, ES8 등 다양한 버전이 존재한다.
현재 가장 많이 쓰이는 것은 ES6이지만 여전히 일부 오래된 브라우저에서는 ES5까지 밖에 동작하지 않는다.
때문에 하위호환성을 위해서 우선 배우는 문법의 대부분을 ES5를 기준으로 할 것이다.
JS는 파이썬과 같은 인터프리터 언어이며 파이썬 처럼 동적 타이핑, 객체 지향을 지원하는 것이 특징인 언어이다.
동적 타이핑 : 변수 선언 시 데이터 타입을 설정하지 않아도, 코드를 실행할 때 미리 데이터를 확인하여 자동으로 데이터 타입을 설정한다.
메모리(RAM)을 사용하는 문법으로 RAM에서 저장 공간을 할당받아 원하는 데이터를 저장한다
이 때 식별자(변수 이름)라는 문자열을 함께 저장하여 데이터가 저장된 메모리의 저장 공간을 기억한다. 사용자는 식별자를 통해 데이터에 접근할 수 있다.
반드시 지켜야하는 규칙으로, 틀릴 경우 에러가 발생한다.
_
, $
만을 사용할 수 있다.필수는 아니나 코드의 가독성을 위해 권장되는 규칙으로, 틀려도 오류가 발생하지는 않는다.
camelCase는 문자열의 첫글자만 소문자로 하고, 띄어쓰기를 해야하는 구간마다 대문자를 사용하여 작성한다.
PascalCase는 camelCase에서 문자열의 첫글자도 대문자를 사용한다.
ES5에서는 var
를 사용하여 변수를 선언한다.
ES6에서는 상수를 나타내는 const
와 변수를 나타내는 let
을 구분하지만 우선은 모두 var
를 사용하자.
// 식별자 1개, 데이터 1개
var data1 = 10;
// 식별자 n개, 데이터 n개
var data2 = 20, data3 = 30;
// 가독성을 위해 아래와 같이 사용하는 것을 권장
var data2 = 20,
data3 = 30;
// 식별자 n개, 데이터 1개
var data4 = data5 = 40;
// console.log() : 데이터를 콘솔창에 출력
console.log(data1, data2, data3, data4, data5)
10 20 30 40 40
저장공간을 효율적으로 사용하기 위한 문법이다.
boolean은 1byte, int는 4byte 등 각 데이터 타입마다 필요한 저장공간이 다른데, 이를 고려하지 않고 무작정 많은 저장공간을 할당하는 것은 비효율적이기 때문에 데이터 타입이 중요하다.
JS는 동적 타이핑을 지원하기 때문에 사용자가 변수 선언 시 자료형을 입력할 필요는 없지만, 데이터 타입이 다르면 연산 시 문제가 발생할 수 있기 때문에 알아두어야 한다.
number
: 숫자 데이터 타입; int와 float을 구분하지 않는다.string
: 문자열 데이터 타입boolean
: 논리값 데이터 타입; true
, false
로 표시한다.function
: 함수 데이터 타입; 코드를 저장한다.object
: 객체 데이터 타입; 파이썬의 딕셔너리, 클래스, 리스트처럼 사용할 수 있는 자료형이다.typeof
은 JS의 예약어 중 하나로 변수의 자료형을 확인할 수 있다.
var data1 = 1.2;
var data2 = 'js';
var data3 = true;
var data4 = function(){ console.log('func')};
var data5 = {key: 'value', func: function(){console.log('func in object')}};
// typeof : 예약어로, 변수의 데이터 타입을 출력
console.log(typeof data1, typeof data2, typeof data3, typeof data4, typeof data5)
>>> `number string boolean function object`
console.log(typeof data5['func'])
>>> `function`
빈 값
이라는 뜻의 데이터 타입이다. undefined 값이 없다는 것을 의도적으로 명시하기 위한 데이터 타입이다.다른 대부분의 언어와 마찬가지로 선언된 데이터 타입을 다른 데이터 타입으로 바꾸는 형변환을 할 수 있다.
자바스크립트는 서로 다른 데이터 타입을 연산할 때 곧바로 오류를 출력하지 않고, 가능한 경우 묵시적으로 형변환을 하여 연산한다.
예를 들어 숫자로 변환이 불가능한 문자열과 숫자 데이터 타입을 연산할 경우 숫자가 문자열로 묵시적 형변환이 되어 연산이 이루어진다.
숫자로 변환이 가능할 경우 문자열 쪽이 숫자로 형변환되어 연산이 이루어진다.
var string = ' '
var number = 5
var number_string = '5'
console.log(string + number)
>>> 5
console.log(number + number_string * number)
>>> 30
CPU 연산을 사용하기 위한 문법이다.
사칙연산, 나눗셈 연산(%
), 거듭제곱 연산(**
) 등은 다른 언어와 똑같이 동작한다.
자바스크립트 역시 소수끼리 연산할 경우 부동 소수점으로 인해 오차가 발생하는 문제가 존재한다.
// 부동 소수점 문제
var data1 = 0.1, data2 = 0.2;
console.log(data1 + data2)
>>> 0.30000000000000004
자바스크립트의 round()
함수는 소수점 자릿수를 지정할 수 없기 때문에, 원하는 자릿수 만큼 10^n을 곱한 뒤 정수로 반올림하고, 다시 10^n으로 나누는 과정을 통해 부동소수점 연산을 처리할 수 있다.
// 반올림 처리를 통한 부동소수점 처리
// 자릿수를 지정할 수 없기 때문에 원하는 자리수까지 곱한 것을 반올림 한 뒤 다시 나눔
console.log(Math.round( (data1 + data2) * 100) / 100)
>>> 0.3
++
, --
)변수의 값을 1씩 증가/감소시키는 연산으로, 증감 연산자의 위치에 따라 작동하는 방식이 조금 다르다.
// ++data : +1 후에 데이터 대입
var data1 = 1, data2 = 2;
data1 = ++data2;
console.log(data1, data2);
>>> 3 3
// data++ : 데이터 대입 후에 +1
var data1 = 1, data2 = 2;
data1 = data2++;
console.log(data1, data2);
>>> 2 3
증감연산자가 변수 뒤에 올 경우, 대입되는 값은 연산 이전의 값이고, 현재 변수의 값만 증가하니 유의해서 사용해야한다.
크게 두 종류의 비교연산자가 있다.
// 비교연산자
// ===, !== : 데이터 타입까지 따져 비교
console.log(1 === '1');
console.log(2 !== '2');
// ==, != : 데이터 타입은 따지지 않고 비교
console.log(1 == '1');
console.log(2 != '2');
데이터 타입을 따지지 않고 비교할 경우, 의도치 않은 작동(에러)을 유발할 수 있으므로 되도록 ===
, !==
을 사용해 보다 엄격하게 조건을 검사하는 것이 권장된다.
&&
: and
연산자
||
: or
연산자
(조건 ? 참 : 거짓)
으로 구성되는 연산자로, 조건문을 한 줄에 간단하게 쓸 수있다는 장점이 있다.
// 삼항 연산자 (조건 ? 참 : 거짓)
var balance = 5000
var withdraw = 7000
console.log(balance >= withdraw ? '인출가능' : '인출불가')
>>> 인출불가
한번에 여러 종류의 연산자를 사용해야할 경우, 연산자의 우선순위를 알아두는 것이 좋다.
대략적으로는 괄호 > 증감 연산자 > 산술 연산자 > 비교 연산자 > 논리 연산자 > 대입(할당) 연산자 순으로 높은 우선순위를 갖는다.
이로 인해 data1 === data2 && data3 !== data4
와 같은 조건문의 순서가 꼬이지 않고 작동한다.
하지만 (data1 === data2) && (data3 !== data4)
처럼 괄호를 통해 우선순위를 명시하는 것도 가독성을 위해 좋은 방법이다.
이하의 코드는 JS 코드를 효율적으로 작성하기 위해 사용하는 것들이다.
if (조건문) { 실행 코드 }
형식으로 사용한다.
else if
를 통해 여러 조건을 검사할 수 있으며 else
를 통해 모든 조건을 만족하지 않는 나머지 경우를 처리한다.
// 학점 출력 (if)
var point = 55;
if (point > 90) {
console.log('Bad');
} else if (point > 70) {
console.log('Not bad');
} else {
console.log('good');
}
>>> good
switch (데이터) { case 조건: 실행 코드 }
형식으로 사용한다.
switch문과 함께 선언된 데이터와 일치하는 case가 있을 경우 해당 코드를 실행한다.
// 승점 출력 (switch)
var point = '승';
switch(point) {
case '승':
console.log('승점', 3);
break;
case '무':
console.log('승점', 1);
break;
default:
console.log('승점', 0);
}
>>> 승점 3
주의할 점은 중간에 case를 만족하여 코드가 실행되면, 아래에 있는 코드들이 case 일치 여부와 상관없이 모조리 실행된다.
이러한 것을 원지 않는다면 break
을 사용해 코드 실행 후 switch문을 빠져 나와야 한다.
// 승점 출력 (switch)
var point = '무';
switch(point) {
case '승':
console.log('승점', 3);
case '무':
console.log('승점', 1);
default:
console.log('승점', 0);
}
>>> 승점 1
>>> 승점 0
JS는 다양한 반복문을 지원하지만 주로 사용하는 것은 for
와 while
이다.
while은 파이썬과 동일하게 동작하므로 설명을 생략하겠다.
JS에서 for loop은 for (변수, 조건, 변수 증감(step)) {반복 코드 내용}
형식으로 사용한다.
정해진 iteration이 끝나면 종료되는 파이썬과 달리 조건을 만족하는 동안 for loop이 계속 실행되기 때문에 증감 조건을 잘못 설정할 경우 무한 루프에 빠질 수 있어 사용에 주의해야한다.
// for loop (변수; 변수 조건; 변수 증감 step)
var count = 3
for (var i = 0; i<count; i++){
console.log('forloop', i);
}
>>> forloop 0
>>> forloop 1
>>> forloop 2
JS에서 함수를 사용하는 목적은 중복된 코드를 묶어 코드의 복사 붙여넣기 없이 손쉽게 재사용하기 위해서이다. 이를 통해 코드의 유지보수성을 향상시킨다.
함수 선언 방법은 크게 두가지로 나눌 수 있다.
// 함수선언 1 : 함수 선언식
plus1(3, 5)
function plus1(n1, n2) {
console.log(n1 + n2);
};
>>> 8
함수 선언식으로 함수를 선언할 경우 함수를 수행하는 코드를 최상단으로 올려서 우선적으로 선언된 뒤 다른 코드들이 실행 된다. 덕분에 위 예시에서 함수 선언보다 먼저 함수를 호출 했음에도 결과가 정상적으로 출력되었다.
이러한 자바스크립트의 특징을 hoisting이라고 한다. 인터프리터가 코드를 미리 살펴본 뒤 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다.
// 표현식
plus5(1, 2)
var plus5 = function (n1, n2) {
console.log(n1 + n2);
};
>>> TypeError: plus5 is not a function
// 표현식 (hoisting이 적용되지 않음)
console.log(plus5)
var plus5 = function (n1, n2) {
console.log(n1 + n2);
};
>>> undefined
표현식은 변수를 선언하듯이 함수를 선언하는 방법을 말한다. 이 경우 plus5라는 변수가 hoisting에 의해 선언은 되었으나, 아직 함수 코드가 할당되지 않아 undefined 데이터 타입이 되었음을 확인할 수 있다.
왜 이러한 차이가 발생하는지 알기 위해서는 TDZ와 hoisting 개념을 알아야 한다.
변수에 데이터를 담는 과정은 크게 3단계로 표현할 수 있다.
자바 스크립트에서 변수를 선언할 경우 선언되는 코드 최상단에서 데이터가 담길 저장 공간을 미리 만들어 놓는다.
var
, function
에 의해 선언된 변수들은 hoisting에 의해 초기화 단계 또는 할당단계까지 코드 최상단에서 이루어진다.
이 때 var
변수는 초기화 단계까지만 진행되고 function
변수는 할당 단계까지 완료된다.
let
, const
에 의해 선언된 변수들은 Declaration phase만 이루어진채로, 변수가 선언된 코드에 도달하기 전까지 값이 undefined로 초기화 되지 않는다.
이때 Declaration Phase와 Initialization phase 사이에서, 스코프가 어떤 저장공간을 가리키지만, 정작 접근할 수 없는 상태를 TDZ라고 한다.
이 때 변수에 접근하려 하면 참조 에러(Reference Error)가 발생한다.
ES6에서는 함수 선언이 더 간단해진다.
// 번외 : ES6 함수 표현식
const plus3 = (n1, n2) => {
console.log(n1 + n2);
}
// 매개변수가 하나라면 소괄호 생략이 가능, 함수가 표현식 하나라면 중괄호도 생략이 가능
const plus3 = n1 => console.log(n1 + 5);
파이썬의 컬렉션 데이터 타입 (리스트, 튜플, 딕셔너리 등)이나 클래스 문법과 유사한 형태로 사용이 가능한 데이터 타입이다
ES6에서는 class
개념을 지원하지만, ES5에서는 object
를 통해 비슷하게 구현해서 사용해야 한다.
// 객체를 컬렉션 데이터 타입으로 사용 (리스트)
var data = [1, 2, 3, 'A', 'B']
console.log(typeof data)
>>> object
// 객체를 컬렉션 데이터 타입으로 사용 (딕셔너리)
var data = {
one: 1,
two: 2,
three: 3
}
console.log(typeof data, data)
>>> object { one: 1, two: 2, three: 3 }
// 객체를 클래스 문법으로 사용
// ES5에는 클래스가 존재하지 않았기 때문에 object를 통해 비슷하게 구현
var obj = {
data: 'js',
plus: (n1, n2) => {return n1 + n2;},
}