
OT 이후 진짜 데브 코스 시작이다. JavaScript 주요 문법을 공부하였다.
공부를 하면서 내가 어디까지 알고 있고 어떤 부분에서 헷갈려 하는지 다시 한번 짚게 되어 좋았다.
1. 변수, 호이스팅, 상수, 자료형, 메모리,
2. 표현식과 연산자
3. 흐름 제어
4. 배열과 객체
5. 스코프와 클로저
수학에서 변수는 변하는 값을 의미하지만 컴퓨터 공학에서 변수는 개발자가 직접 메모리에 값을 할당하는 것을 의미한다.
자바스크립트에서 변수를 선언하는 방법은 var, let이 존재한다.
var는 ES6이전에 나온 선언 방법으로 호이스팅으로 인해 권장하지 않으며 window 객체의 프로퍼티 이다.
let은 ES6이후에 나온 선언 방법으로 변수를 선언 시 권장하는 키워드이다.
let data1 = 1;
var data2 = 2;
상수는 변하지 않는 값을 의미한다. 즉 한번 할당을 했을 경우 재할당이 금지된다.
const 키워드를 사용한다. ES6이후에 추가되었다.
const data = 1;
const 키워드로 선언한 상수에 재할당을 했을 경우 다음과 같은 에러가 발생하게 된다.

자바스크립트는 원시 타입과 참조 타입으로 나누어진다.
원시타입
| 타입 | 특징 | 값 |
|---|---|---|
| Number | 숫자와 관련된 타입을 의미함 | 정수,실수,nan(연산불가능),Infinity(무한대) |
| String | 문자와 관련된 타입을 의미함 | 작은따옴표(''), 큰따옴표(""), 백틱(``) |
| Boolean | 논리적 참, 거짓을 나타냄 | true,false |
| undefined | 자바스크립트 엔진이 변수를 초기화할 때 사용하는 값 | undefined 유일 값 |
| null | 변수에 값이 없다는 것을 의도적으로 명시할때 사용하는 값 | null 유일 값 |
| Symbol | 다른 값과 중복되지 않는 유일무일한 값이다. | Symbol 키워드로 생성 |
객체 타입
const person = {name: '홍길동'}let arr = [1,2,3,4,5]let func = function (){};일반적으로 메모리는 할당 -> 사용 -> 해제의 순서를 이룬다. 변수를 생성 했을때 변수는 메모리에 할당이 되고 값을 넣어 사용한다. 메모리의 공간은 한정되어 있기 때문에 사용이 완료되었을 때는 할당된 공간을 해제해야 한다.
우리가 사용하는 자바스크립트는 가비지컬렉터가 있어 개발자가 직접 메모리에 접근하지 않아도 가비지컬렉터가 더이상 사용되지 않는 값을 메모리에서 해제시킨다.
let a = 1;
let b = a;
지금까지 나는 원시 값은 같은 값일 경우 서로 다른 메모리 공간에 저장되는 것으로 알고 있었다.
즉 위 코드를 실행했을 때 메모리 영역은 그림처럼 30이라는 값이 복사되어 서로 다른 메모리에 할당되는 줄 알고있었다. 그런데 질문을 통해 값은 하나의 주소에서 참조되고 있음 알게되었다.(답변해주신 멘토님 정말 감사합니다!!)

위 사진에서 변수 a, b는 다른 주소이고 참조하고 있는 값 1은 @173 주소를 참조하는 것을 알 수 있었다.
자바스크립트엔진은 CallStack영역과 Heap영역으로 이뤄져 있으며 원시타입과, 참조타입을 나누어 할당한다.
CallStack: 원시타입
Heap : 참조타입
const a = 1;
const b = 10;
const c = [];
c.push(1);
c.push(2);
위 코드를 실행 했을때 순차적으로 CallStack에 쌓이며 배열의 경우 Heap 영역의 배열주소를 참조한다.

호이스팅이란 var키워드, 함수선언문을 사용했을때 자바스크립트 엔진에 의해 선두로 끌어올려 초기화 되는 것을 의미한다.
var 키워드 사용
console.log(score);
var score;
위 코드 예제에서 score를 선언하기 전에 먼저출력을 했지만 호이스팅으로 인해 에러가 발생하지 않는다.
function 선언문
console.dir(add);
console.log(add(2, 5));
function add(x, y) {
return x + y;
}
위 예제 역시 add 함수가 선언하기 전에 먼저 함수를 실행시켰지만 호이스팅으로 정상적으로 실행된 것을 확인할 수 있다.
let,const에서는?
let과 const에서는 호이스팅이 발생하지만 호출전에 초기화 되지 않아 참조에러가 발생하게 된다. 이것을 일시적 사각지대(TDZ:Temporal Dead Zone)라고 하며 아래 예제에서 확인해 보자

호이스팅이 발생하는 이유를 알기 위해 실행 컨텍스트 알아야 하지만 이 글에서 작성하기에는 너무 길어 해당 내용은 따로 정리 중이다.
어떠한 결과가 값으로 평가되는 식을 의미한다.
//리터럴 표현식
'Hello'
//식별자 표현식(선언이 이미 존재한다고 가정)
sum
person.name
arr[1]
//연산자 표현식10 + 20
sum = 10
sum !== 10
//함수/메서드 호출 표현식(선언이 이미 존재한다고 가정)
square()
person.getName()
오른쪽에 표현식을 왼쪽 피연산자에 할당하는 연산자
| 할당 연산자 | 예 | 동일 표현 |
|---|---|---|
| = | x = 5 | x = 5 |
| += | x += 5 | x = x + 5 |
| -= | x -= 5 | x = x - 5 |
| *= | x *= 5 | x = x * 5 |
| /= | x /= 5 | x = x / 5 |
| %= | x %= 5 | x = x % 5 |
좌측과 우측의 피연산자를 비교하는 연산자 true,false를 반환한다.
| 비교 연산자 | 의미 | 사례 | 설명 |
|---|---|---|---|
| == | 동등 비교 | x == y | x와 y의 값이 같음 |
| === | 일치 비교 | x === y | x와 y의 값과 타입이 같음 |
| != | 부동등 비교 | x != y | x와 y의 값이 다름 |
| !== | 불일치 비교 | x !== y | x와 y의 값과 타입이 다름 |
비트를 조작하는 연산자
(논리합의 경우 파이프 기호가 테이블 마크다운으로 인해 적용되지 않아 l로 대체)
| 비트 연산자 | 의미 |
|---|---|
| l | 논리합(OR) |
| & | 논리곱(AND) |
| ~ | 부정(NOT) |
| ^ | 배타적 논리합(XOR) |
| << | 왼쪽 쉬프트 |
| >> | 오른쪽 쉬프트 |
참과 거짓을 검증하는 연산자
| 논리연산자 | 의미 |
|---|---|
| && | 논리곱(AND) |
| ! | 부정(NOT) |
조건? 참 : 거짓 형태를 가지는 연산자
let x = 2;
let result = x % 2 ? '홀수' : '짝수';
객체의 속성이 있는지 확인하는 연산자
const person = {
name:"TEST"
}
console.log("name" in person); // true
console.log("address" in person); // false
피연산자의 타입을 반환하는 연산자(문자열로 반환된다);
const x = 10;
const y = "string";
const z = false;
console.log(typeof x); // number
console.log(typeof y); // string
console.log(typeof z); // boolean
조건이 맞을 때만 실행되는 문법이다. 소괄호 안에 조건을 넣고 조건이 참인 경우 중괄호 안의 내용을 실행시킨다.
예제
if(true){
console.log('hello');
}
주의사항
false 뿐만 아닌 null,0,NaN,undefined,'' 도 거짓이다.
if문과 같지만 거짓일 경우 실행하는 else가 추가되었다.
예제
if(false){
console.log('true');
}else{
console.log('false')
}
if문과 같지만 거짓일 경우 한번더 조건을 체크 후 else로 빠지게된다.
if(false){
console.log('false');
}else if(true){
console.log('true')
}else{
console.log('false');
}
괄호 안 값에 따라 분기되는 문법
예제
const grade = "B";
switch (grade) {
case "A":
console.log("A grade");
break;
case "B":
console.log("B grade");
break;
case "C":
console.log("C grade");
break;
case "D":
console.log("D grade");
break;
default:
console.log("Unknown");
조건문의 결과가 거짓이 되면 반복을 종료한다.
예제
for (let i = 0; i < 10; i+=1) {
console.log(i);
}
괄호안 조건이 거짓이 될 때까지 반복
예제
let x = 0;
while (x < 10){
x += 1;
console.log(x);
}
로직을 먼저 실행한 다음 조건을 검사
예제
let x = 0;
do {
console.log("Fire");
} while (x > 10);
연관된 데이터를 연속적인 형태로 저장하는 복합 타입으로 순서대로 번호가 붙는다.
const arr1 = new Array();
const arr2 = [];
const arr3 = [1,2,3,4,5];
const arr4 = new Array(5);
const arr5 = new Array(5).fill(5);
const arr6 = Array.from(Array(5), function(v,k){
return k + 1;
});
const arr = [1,2,3,4,5];
//추가
arr.push(6);
//첫번째 요소 삭제
arr.shift();
//요소를 배열의 맨 앞쪽에 추가하고
arr.unShift()
//중간요소 출력
arr.slice(2,4);
//중간요소 삭제
arr.aplice(2,4);
for문
const arr = [1,2,3,4,5];
for(let i=0; i<arr.length; i++){
console.log(arr[i]);
}
for of문
const arr = [1,2,3,4,5];
for(const item of arr){
console.log(item);
}
MDN에서 검색해서 사용해보는 것을 추천한다.
Key, value로 여러 값을 가지는 타입
예제
const obj = { name: "test" }
//객체 추가
obj['test1'] = 1;
obj.test2 = 2;
//객체 삭제
delete obj.test2;
//객체 순회
for(const key in obj){
console.log(key, obj[key]);
}
변수가 참조되는 범위를 말한다. 전역 스코프, 블록 스코프, 함수 스코프의 종류가 있다.
var: 경우 함수 스코프를 가진다
let,const: 블록 스코프를 가진다.
함수가 선언된 환경의 스코프를 기억하여 함수가 스코프 밖에서 실행될 때에도 기억한 스코프에 접근할 수 있게 만드는 문법이다.
예제
const x = 1;
function outer() {
const x = 10;
const inner = function () {
console.log(x);
}
return inner;
}
const innerFunc = outer();
innerFunc() // 10;
우리가 클로저를 알아야 하는 이유는 유용하게 사용하기 보단 알기 힘든 버그를 쉽게 수정하기 위해서이다.
function counting(){
let i = 0;
for (i = 0; i < 5; i += 1) {
setTimeout(function(){
console.log(i);
}, i * 100)
}
}
counting()
위 코드의 경우 setTimeout이 응답을 하기전에 루프가 먼저실행되어 5,5,5,5,5가 출력된다.
function counting(){
for (let i = 0; i < 5; i += 1) {
setTimeout(function(){
console.log(i);
}, i * 100)
}
}
counting();
밖에 선언한 let i를 for문 안에서 사용한다.
function counting(){
let i = 0;
for (i = 0; i < 5; i += 1) {
(function(number){
setTimeout(function(){
console.log(number);
}, i * 100)
})(i)
}
}
counting()
즉시 실행함수를 만들어 루프마다 클로저를 만든다.