비개발자를 위한 앱 개발 시리즈의 다섯 번째 이야기로, 자바스크립트의 기초 문법에 대해 다루고 있습니다. ES6 문법에 대한 두 번째 강의를 듣고있는데 처음부터 이해하기 어려워서, 벨로퍼트와 함께하는 모던 자바스크립트를 참고하여 자바스크립트 기초 문법부터 익히기로 했습니다. 공부한 내용을 잊지 않도록 개인적으로 취약한 부분을 발췌해 이 포스트에 정리해 두었습니다.
자바스크립트 기초 문법: 1. 변수와 상수
변수와 상수는 특정 이름에 특정 값을 담을 때 사용한다. 예를 들어 value 라는 이름에 1 이라는 값을 넣는다고 가정해보면 코드 아래와 같습니다.
let value = 1;
특정 이름에 특정 값을 설정하는 것을 선언 이라고 부릅니다다. 값을 선언 할 때에는 두 가지 종류가 있는데, 하나는 변수이고, 하나는 상수입니다.
변수
변수는 바뀔 수 있는 값을 말합니다. 한번 값을 선언하고 나서 바꿀 수 있습니다. 아래 코드와 같이 value 라는 이름에 1이라는 값을 선언했다가 2로 다시 선언하면 2로 출력됩니다. 변수를 선언 할 때에는 이렇게 let 이라는 키워드를 사용합니다.
let value = 1;
console.log(value);
// 1
value = 2;
console.log(value);
// 2
여기서 주의할 점은 아래와 같은 코드는 에러가 발생합니다. 한번 선언했으면 똑같은 이름으로 선언하지 못합니다. (단, 다른 블록 범위 내에서는 똑같은 이름으로 사용 가능합니다)
let value = 1;
let value = 2;
// Error
상수
상수는 한번 선언하고 값이 바뀌지 않는 값을 의미합니다다. 즉, 값이 고정적입니다. 상수를 선언 할 때에는 다음과 같이 const 라는 키워드를 사용하여 선언합니다.
const value = 1;
아래와 같은 코드는 에러가 발생합니다. 한번 상수로 선언했으면 값을 바꿀 수 없으며, 변수 선언과 마찬가지로 한번 선언 했으면 같은 이름으로 선언할 수 없습니다.
const value = 1;
value = 2;
// Error
const value = 1;
const value = 2;
// Error
추가적으로, IE9, IE10 같은 구형 브라우저에서는 let 과 const 를 사용 할 수 없습니다. 하지만, 보통 개발을 하게 될 때는 Babel 과 같은 도구를 사용하여 코드가 구형 브라우저에서도 돌아갈 수 있게끔 변환 작업을 합니다.
자바스크립트 기초 문법: 2. 연산자
연산자는 프로그래밍 언어에서 특정 연산을 하도록 하는 문자입니다. 연산자에는 산술 연산자( +, -, *, / , ++), 대입 연산자 ( +=, -=, *=, /= ), 논리 연산자 ( !, &&, || ), 비교 연산자 ( === ) 가 있습니다.
비교연산자
비교 연산자는 두 값을 비교 할 때 사용 할 수 있다.
const a = 1;
const b = 1;
const equals = a === b;
console.log(equals);
// true
두 값이 일치 하는지 확인 할 때 = 문자를 3번 사용하는데, 2개로도 비교를 할 수는 있습니다. 차이점은 2개 있을 때에는 타입 검사까지는 하지 않는다는 것입니다. 즉, 숫자 1과 문자 ‘1’ 이 동일한 값으로 간주합니다. 따라서 두 값이 일치하는지 비교 할 때에는 == 대신 === 를 사용 할 것을 권장합니다. == 를 사용하다 보면 실수를 할 확률이 높아집니다.
두 값이 일치하지 않는지 확인 할 때에는 !== 를 사용하면 됩니다. 역시 != 를 사용하게 되면 타입 검사를 하지 않으므로 !== 를 사용하기를 권장합니다.
const value = 1 !== '1';
// true
const value = 1 != '1';
// false
자바스크립트 기초 문법: 3. 조건문
조건문을 사용하면 특정 조건이 만족됐을 때 특정 코드를 실행할 수 있습니다.
if 문
조건이 만족됐을 때 실행시킬 코드가 { } 로 감싸져 있는데, 이를 코드 블록이라고 합니다. 만약에 조건이 true 가 된다면 우리가 지정한 코드가 실행되는 것이고, false 가 된다면 코드가 실행되지 않습니다.
const a = 1;
if (a + 1 === 2) {
console.log('a + 1 이 2 입니다.');
// a + 1 이 2 입니다.
}
앞서 let 과 const 에 대해 배울 때, 다른 블록 범위에서는 똑같은 이름으로 선언 할 수도 있다고 했습니다. 아래와 같은 코드를 실행했을 때 어떻게 출력되는지 살펴봅시다.
const a = 1;
if (true) {
const a = 2;
console.log('if문 안의 a 값은 ' + a);
// if문 안의 a 값은 2
}
console.log('if문 밖의 a 값은 ' + a);
// if문 밖의 a 값은 1
자바스크립트 기초 문법: 4. 함수
특정 코드를 하나의 명령으로 실행 할 수 있게 해주는 기능입니다다. 예를 들어 특정 값들의 합을 구하고 싶을 때는 다음과 같이 함수로 만들어 작성할 수 있습니다.
function add(a, b) {
return a + b;
}
const sum = add(1, 2);
console.log(sum);
// 3
함수를 만들 때는 function 키워드를 사용하며, 함수에서 어떤 값을 받아올지 정해주는데 이를 파라미터(매개변수)라고 부릅니다. 함수 내부에서 return 키워드를 사용하여 함수의 결과물을 지정 할 수 있습니다. return을 하게 되면 함수가 끝나는 것이며, return 아래의 코드는 호출되지 않습니다.
연습으로 name 이라는 파라미터를 넣으면 콘솔에 ‘Hello name!’ 이라는 결과를 출력하는 코드를 작성해봅시다.
function hello(name) {
console.log('Hello, ' + name + '!');
}
hello('Postype');
// Hello, Postype!
ES6의 템플릿 리터럴 (Template Literal) 문법을 사용하여 작성하면 아래와 같습니다.
function hello(name) {
console.log(`Hello, ${name}!`);
}
hello('Postype');
// Hello, Postype!
화살표 함수
함수를 선언하는 방식 중 또 다른 방법은 화살표 함수 문법을 사용 하는 것입니다. function 키워드 대신에 => 문자를 사용해서 함수를 구현하는데, 화살표의 좌측에는 함수의 파라미터, 화살표의 우측에는 코드 블록이 들어옵니다.
const add = (a, b) => {
return a + b;
};
console.log(add(1, 2));
// 3
위와 같이 코드 블록 내부에서 바로 return 을 하는 경우는 다음과 같이 줄여서 쓸 수도 있습니다.
const add = (a, b) => a + b;
console.log(add(1, 2));
// 3
화살표 함수와 일반 function 으로 만든 함수와의 주요 차이점은 화살표 함수에서 가르키는 this 와 function에서 가르키는 this가 서로 다르다는 것입니다. (이에 대한 자세한 내용은 추후에 다루도록 함)
자바스크립트 기초 문법: 5. 객체
객체는 우리가 변수 혹은 상수를 사용하게 될 때 하나의 이름에 여러 종류의 값을 넣을 수 있게 해줍니다. 객체를 선언 할 때에는 중괄호 { } 문자 안에 원하는 값들을 넣어주면 됩니다. 값을 집어 넣을 때에는 키: 원하는 값 형태로 넣으며, 키에 해당하는 부분은 공백이 없어야합니다.
const dog = {
name: '댕댕이',
age: 2
};
console.log(dog.name);
// 댕댕이
console.log(dog.age);
// 2
연습 삼아 다음과 같이 코드를 작성해 봅시다. 각 키에 해당하는 값이 출력되는 것을 확인할 수 있습니다.
const ironMan = {
name: '토니 스타크',
actor: '로버트 다우니 주니어',
alias: '아이언맨'
};
const captainAmerica = {
name: '스티븐 로저스',
actor: '크리스 에반스',
alias: '캡틴 아메리카'
};
console.log(ironMan);
// {"name":"토니 스타크","actor":"로버트 다우니 주니어","alias":"아이언맨"}
console.log(captainAmerica);
// {"name":"스티븐 로저스","actor":"크리스 에반스","alias":"캡틴 아메리카"}
함수에서 객체를 파라미터로 받기
함수를 새로 만들어서 방금 만든 객체를 파라미터로 받아와서 사용해 봅시다.
const ironMan = {
name: '토니 스타크',
actor: '로버트 다우니 주니어',
alias: '아이언맨'
};
const captainAmerica = {
name: '스티븐 로저스',
actor: '크리스 에반스',
alias: '캡틴 아메리카'
};
function print(hero) {
const text = `${hero.alias}(${hero.name}) 역할을 맡은 배우는 ${hero.actor} 입니다.`;
console.log(text);
}
print(ironMain);
// 아이언맨(토니 스타크) 역할을 맡은 배우는 로버트 다우니 주니어 입니다.
print(captainAmerica);
// 캡틴 아메리카(스티븐 로저스) 역할을 맡은 배우는 크리스 에반스 입니다.
객체 비구조화 할당 (객체 구조 분해)
print 함수를 보면 파라미터로 받아온 hero 내부의 값을 조회 할 때 마다 hero. 를 입력하고 있는데, 객체 비구조화 할당이라는 문법을 사용하면 코드를 더욱 짧고 보기 좋게 작성 할 수 있습니다.
const ironMan = {
name: '토니 스타크',
actor: '로버트 다우니 주니어',
alias: '아이언맨'
};
const captainAmerica = {
name: '스티븐 로저스',
actor: '크리스 에반스',
alias: '캡틴 아메리카'
};
function print(hero) {
const { alias, name, actor } = hero;
// 객체에서 값들을 추출해서 새로운 상수로 선언해 주는 역할
const text = `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`;
console.log(text);
}
print(ironMain);
// 아이언맨(토니 스타크) 역할을 맡은 배우는 로버트 다우니 주니어 입니다.
print(captainAmerica);
// 캡틴 아메리카(스티븐 로저스) 역할을 맡은 배우는 크리스 에반스 입니다.
여기서 더 나아가면, 파라미터 단계에서 객체 비구조화 할당을 할 수도 있습니다.
const ironMan = {
name: '토니 스타크',
actor: '로버트 다우니 주니어',
alias: '아이언맨'
};
const captainAmerica = {
name: '스티븐 로저스',
actor: '크리스 에반스',
alias: '캡틴 아메리카'
};
function print({ alias, name, actor }) {
const text = `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`;
console.log(text);
}
print(ironMain);
// 아이언맨(토니 스타크) 역할을 맡은 배우는 로버트 다우니 주니어 입니다.
print(captainAmerica);
// 캡틴 아메리카(스티븐 로저스) 역할을 맡은 배우는 크리스 에반스 입니다.
객체 안에 함수 넣기
객체 안에 함수를 넣을 수도 있습니다. 함수가 객체 안에 들어가게 되면, this 는 자신이 속해있는 객체를 가르키게 됩니다.
const dog = {
name: '댕댕이',
sound: '왈왈',
say: function say() { // function() { <-함수 이름을 작성하지 않아도 무방하다.
console.log(this.sound);
}
};
dog.say();
// 왈왈
객체 안에 함수를 넣을 때, 화살표 => 함수로 선언한다면 제대로 작동하지 않습니다. function 으로 선언한 함수는 this 가 제대로 자신이 속한 객체를 가르키게 되는데, 화살표 함수는 그렇지 않기 때문입니다.
자바스크립트 기초 문법: 6. 배열
객체는 하나의 변수나 상수에 여러 가지 정보를 담기 위함이었다면, 배열은 여러 개의 항목들이 들어있는 리스트와 같습니다. 예를 들어 아래와 같이 숫자 배열을 선언해 봅시다. 배열을 선언 할 때에는 이렇게 대괄호 [ ] 안에 감싸줍니다.
const = array [1, 2, 3, 4, 5];
배열 안에는 어떤 값이던지 넣을 수 있습니다. 아래와 같이 객체 배열을 만들어 봅시다.
const objects = [{name: '댕댕이'}, {name: '냥냥이'}]
// 배열을 선언하고 나서, n 번째 항목을 조회하고 싶을 땐 다음과 같이 할 수 있다.
// objects[n];
console.log(objects[0]);
// {"name":"댕댕이"}
console.log(objects[1]);
// {"name":"냥냥이"}
배열에 새 항목 추가하기
배열에 새로운 항목을 추가 할 때에는 배열이 지니고 있는 내장 함수인 push 함수를 사용합니다.
const objects = [{name: '댕댕이'}, {name: '냥냥이'}]
objects.push({
name: '개냥이'
});
console.log(objects);
// [{"name":"댕댕이"},{"name":"냥냥이"},{"name":"개냥이"}]
배열의 크기 알아내기
배열의 크기를 알아낼 때에는 배열의 length 값을 확인한다.
const objects = [{name: '댕댕이'}, {name: '냥냥이'}]
console.log(objects.length);
// 2
자바스크립트 기초 문법: 7. 반복문
반복문은 특정 작업을 반복적으로 할 때 사용할 수 있는 구문입니다.
for
for 문은 가장 기본적인 반복문입니다. 특정 값에 변화를 주어가면서 우리가 정한 조건이 만족되면 계속 반복합니다.
for (let i = 0; i < 10; i++){ // 초기 구문; 조건 구문; 변화 구문;
console.log(i);
}
// 0
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
While
while 문은 특정 조건이 참이라면 계속해서 반복하는 반복문입니다. for 문은 특정 숫자를 가지고 숫자의 값을 비교하고 증감해주면서 반복을 한다면, while문은 조건을 확인만 하면서 반복을 합니다. 때문에 조건문 내부에서 변화를 직접 주어야 합니다.
let i = 0;
while (i<10){
console.log(i);
i++;
}
객체를 위한 반복문 for…in
객체를 위한 반복문을 알아보기 전에, 객체의 정보를 배열 형태로 받아올 수 있는 함수 몇 가지를 알아봅시다.
const doggy = {
name: '댕댕이',
sound: '멍멍',
age: 2
};
console.log(Object.entries(doggy));
// [["name","댕댕이"],["sound","멍멍"],["age",2]]
console.log(Object.keys(doggy));
// ["name","sound","age"]
console.log(Object.values(doggy));
// ["댕댕이","멍멍",2]
각 함수의 역할은 다음과 같습니다.
- Object.entries: [[키, 값], [키, 값]] 형태의 배열로 변환
- Object.keys: [키, 키, 키] 형태의 배열로 변환
- Object.values: [값, 값, 값] 형태의 배열로 변환
객체가 지니고 있는 값에 대하여 반복을 하고 싶다면 위 함수들을 사용해도 되고, for…in 구문을 사용해도 됩니다.
break 와 continue
반복문 안에서는 break 와 continue 를 통하여 반복문에서 벗어나거나, 그 다음 루프를 돌게끔 할 수 있습니다.
for (let i = 0; i < 10; i++ ){
if (i === 2) continue; // 다음 루프를 실행
console.log(i);
if (i === 5) break; // 반복문을 끝내기
}
// 0
// 1
// 3
// 4
// 5
자바스크립트 기초 문법: 8. 배열 내장함수
배열을 다룰 때 알고 있으면 유용한 다양한 내장 함수들에 대하여 알아 봅시다.
forEach
forEach 는 가장 쉬운 배열 내장함수입니다. 기존에 우리가 배웠던 for 문을 대체할 수 있습니다. 예를 들어 다음과 같은 텍스트 배열은 아래와 같이 작성할 수 있습니다.
const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];
// 배열 안에 있는 모든 원소들을 모두 출력해야 한다면 for 문을 사용하여 다음과 같이 구현할 수 있다.
for (let i = 0; i < superheroes.length; i++){
console.log(superheroes[i]);
}
// 아이언맨
// 캡틴 아메리카
// 토르
// 닥터 스트레인지
// 배열의 forEach 함수를 사용하면 다음과 같이 구현 할 수 있습니다. 출력되는 값은 동일하다.
superheroes.forEach(hero => {
console.log(hero);
});
// 아이언맨
// 캡틴 아메리카
// 토르
// 닥터 스트레인지
forEach 함수의 파라미터로는 각 원소에 대하여 처리하고 싶은 코드를 함수로 넣어줍니다. 이 함수의 파라미터 hero는 각 원소를 가르키게 됩니다.
이렇게 함수형태의 파라미터를 전달하는 것을 콜백함수 라고 부릅니다. 함수를 등록해주면 forEach 가 실행을 해주는 것입니다.
map
map 은 배열 안의 각 원소를 변환할 때 사용되며 이 과정에서 새로운 배열이 만들어집니다.
예를 들어 다음과 같은 배열이 있다고 가정해 봅시다.
const array = [1, 2, 3, 4, 5, 6, 7, 8];
배열 안의 모든 숫자를 제곱해서 새로운 배열을 만들어야 한다고 했을 때, map을 사용하지 않고 지금까지 배운 것으로만 구현한다면 아래와 같이 작성할 수 있습니다.
// for 문을 사용하는 방법
const array = [1, 2, 3, 4, 5, 6, 7, 8];
const newArray = [];
for (let i = 0; i < array.length; i++){
newArray.push(array[i] * array[i]);
}
console.log(newArray);
// [1,4,9,16,25,36,49,64]
// forEach 함수를 사용하는 방법
const array = [1, 2, 3, 4, 5, 6, 7, 8];
const newArray = [];
array.forEach(n => {
newArray.push(n * n);
});
console.log(newArray);
// [1,4,9,16,25,36,49,64]
하지만 map을 사용한다면 더 짧은 코드로 구현할 수 있습니다.
const array = [1, 2, 3, 4, 5, 6, 7, 8];
const newArray = array.map(n => n * n);
console.log(newArray);
// [1,4,9,16,25,36,49,64]
indexOf
indexOf 는 원하는 항목이 몇번째 원소인지 찾아주는 함수입니다.
const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];
만약 위와 같은 배열에서 ‘토르’가 몇번째 항목인지 알고 싶다면 아래와 같이 작성해주면 됩니다.
const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];
const index = superheroes.indexOf('토르');
console.log(index);
// 2
findIndex
만약 배열 안에 있는 값이 숫자, 문자열, 또는 불리언이라면 찾고자 하는 항목이 몇번째 원소인지 알아내려면 indexOf 를 사용하면 됩니다. 하지만, 배열 안에 있는 값이 객체이거나 배열이라면 indexOf 로 찾을 수 없습니다. 이때는 findIndex 함수에 검사하고자 하는 조건을 반환하는 함수를 넣어서 찾을 수 있습니다.
const todos = [
{
id: 1,
text: '자바스크립트 입문',
done: true
},
{
id: 2,
text: '함수 배우기',
done: true
},
{
id: 3,
text: '객체와 배열 배우기',
done: true
},
{
id: 4,
text: '배열 내장함수 배우기',
done: false
}
];
const index = todos.findIndex(todo => todo.id === 3);
console.log(index);
// 2
find
find 함수는 findIndex 랑 비슷한데 찾아낸 값이 몇번째인지 알아내는 것이 아니라 찾아낸 값 자체를 반환합니다.
const todos = [
{
id: 1,
text: '자바스크립트 입문',
done: true
},
{
id: 2,
text: '함수 배우기',
done: true
},
{
id: 3,
text: '객체와 배열 배우기',
done: true
},
{
id: 4,
text: '배열 내장함수 배우기',
done: false
}
];
const todo = todos.find(todo => todo.id === 3);
console.log(todo);
// {"id":3,"text":"객체와 배열 배우기","done":true}
filter
filter 함수는 배열에서 특정 조건을 만족하는 값들만 따로 추출하여 새로운 배열을 만듭니다. 예를 들어, 우리가 방금 만들었던 todos 배열에서 done 값이 false 인 항목들만 따로 추출해서 새로운 배열을 만들어봅시다.
const todos = [
{
id: 1,
text: '자바스크립트 입문',
done: true
},
{
id: 2,
text: '함수 배우기',
done: true
},
{
id: 3,
text: '객체와 배열 배우기',
done: true
},
{
id: 4,
text: '배열 내장함수 배우기',
done: false
}
];
const taskNotDone = todos.filter(todo => todo.done === false);
console.log(taskNotDone);
// [{"id":4,"text":"배열 내장함수 배우기","done":false}]
filter 함수에 넣는 파라미터는 조건을 검사하는 함수를 넣어주며, 이 함수의 파라미터로 각 원소의 값을 받아오게 됩니다. 방금 작성한 코드는 아래와 같이 입력 할 수도 있습니다.
const tasksNotDone = todos.filter(todo => !todo.done);
splice
splice 는 배열에서 특정 항목을 제거할 때 사용합니다.
아래 배열에서 30 을 지운다고 가정해 봅시다. 그러면 30이 몇번째 index 인지 알아낸 이후, 이를 splice 를 통해 지워줄 수 있습니다.
const numbers = [10, 20, 30, 40];
const index = numbers.indexOf(30);
numbers.splice(index, 1); // 인덱스 0부터 시작해서 1개를 지움
console.log(numbers);
// [10,20,40]
splice 를 사용 할 때 첫 번째 파라미터는 어떤 인덱스부터 지울지를 의미하고, 두 번째 파라미터는 그 인덱스부터 몇 개를 지울지를 의미합니다.
slice
slice 는 배열을 잘라낼 때 사용하는데, splice와 다른 점은 기존의 배열은 건드리지 않는 다는 것입니다.
const numbers = [10, 20, 30, 40];
const sliced = numbers.slice(0, 2); // 인덱스 0부터 시작해서 2개까지 자름
console.log(sliced);
// [10, 20]
console.log(numbers);
// [10, 20, 30, 40]
slice 를 사용 할 때 첫 번째 파라미터는 어디서부터 자를지를 의미하고, 그리고 두 번째 파라미터는 어디까지 자를지를 의미합니다.
shift 와 pop
shift 는 첫 번째 원소를 배열에서 추출해 줍니다. 추출하는 과정에서 배열에서 해당 원소는 사라집니다.
const numbers = [10, 20, 30, 40];
const value = numbers.shift();
console.log(value);
// 10
console.log(numbers);
// [20, 30, 40]
pop은 shift와 반대로 맨 마지막 원소를 배열에서 추출해 줍니다.
const numbers = [10, 20, 30, 40];
const value = numbers.pop();
console.log(value);
// 40
console.log(numbers);
// [10, 20, 30]
unshift
unshift 는 shift 의 반대이다. 배열의 맨 앞에 새 원소를 추가해 줍니다.
const numbers = [10, 20, 30, 40];
numbers.unshift(5);
console.log(numbers);
// [5,10,20,30,40]
concat
concat 은 여러 개의 배열을 하나의 배열로 합쳐줍니다.
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const concated = arr1.concat(arr2);
console.log(concated);
// [1,2,3,4,5,6]
여기서 concat 함수는 arr1 과 arr2 에 변화를 주지 않습니다.
join
join 은 배열 안의 값들을 문자열 형태로 합쳐줍니다.
const array = [1, 2, 3, 4, 5];
console.log(array.join());
// 1,2,3,4,5
console.log(array.join(' '));
// 1 2 3 4 5
console.log(array.join(', '));
// 1, 2, 3, 4, 5
reduce
배열의 요소들을 처리하여 하나의 값을 도출해 내는 함수입니다.
만약 주어진 배열에 대하여 총합을 구해야 하는 상황이 왔다고 가정했을 때 reduce 함수를 사용하면 아래와 같이 작성할 수 있습니다.
const numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, current) => accumulator + current, 0);
console.log(sum);
// 15
첫 번째 파라미터는 accumulator 와 current 를 파라미터로 가져와서 결과를 반환하는 콜백함수이며, 두 번째 파라미터는 reduce 함수에서 사용 할 초깃값입니다.
파라미터 값이 어떻게 전달되는지 확인하고 싶다면 아래와 같이 작성해 봅시다.
const numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((accumulator, current) => {
console.log({ accumulator, current });
return accumulator + current;
}, 0);
console.log(sum);
// {"accumulator":0,"current":1}
// {"accumulator":1,"current":2}
// {"accumulator":3,"current":3}
// {"accumulator":6,"current":4}
// {"accumulator":10,"current":5}
// 15
자바스크립트 기초 문법: 9. 프로토타입과 클래스
객체 생성자
프로토타입과 클래스에 대해서 알아보기 전에 우선 객체 생성자라는 것을 알아봅시다. 객체 생성자는 함수를 통해서 새로운 객체를 만들고 그 안에 넣고 싶은 값 혹은 함수들을 구현 할 수 있게 해줍니다.
function Animal (type, name, sound){
this.type = type;
this.name = name;
this.sound = sound;
this.say = function(){
console.log(this.sound);
};
}
const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');
dog.say();
// 멍멍
cat.say();
// 야옹
객체 생성자를 사용 할 때는 보통 함수의 이름을 대문자로 시작하고, 새로운 객체를 만들 때에는 new 키워드를 앞에 붙여주어야 합니다. 위 코드를 보면 dog 가 가지고 있는 say 함수와 cat 이 가지고 있는 수행하는 코드가 똑같음에도 불구하고 객체가 생성 될 때 마다 함수도 새로 만들어져서 this.say 로 설정이 되고 있습니다. 같은 객체 생성자 함수를 사용하는 경우, 특정 함수 또는 값을 재사용 할 수 있는데 이것이 바로 프로토타입입니다.
프로토타입
프로토타입은 다음과 같이 객체 생성자 함수 아래에 .prototype.[원하는키] = 코드를 입력하여 설정 할 수 있습니다.
function Animal (type, name, sound){
this.type = type;
this.name = name;
this.sound = sound;
}
Animal.prototype.say = function() {
console.log(this.sound);
};
const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');
dog.say();
// 멍멍
cat.say();
// 야옹
객체 생성자 상속받기
예를 들어 우리가 Cat 과 Dog 라는 새로운 객체 생성자를 만든다고 가정해 봅시다. 그리고 해당 객체 생성자들에서 Animal 의 기능을 재사용한다고 가정해 봅시다. 그렇다면, 이렇게 구현 할 수 있습니다.
function Animal (type, name, sound){
this.type = type;
this.name = name;
this.sound = sound;
}
Animal.prototype.say = function() {
console.log(this.sound);
};
function Dog (name, sound){
Animal.call(this, '개', name, sound);
}
Dog.prototype = Animal.prototype;
function Cat (name, sound){
Animal.call(this, '고양이', name, sound);
}
Cat.prototype = Animal.prototype;
const dog = new Dog('멍멍이', '멍멍');
const cat = new Cat('야옹이', '야옹');
dog.say();
// 멍멍
cat.say();
// 야옹
클래스
ES6 에서부터는 class 라는 문법이 추가되었는데, 우리가 객체 생성자로 구현했던 코드를 조금 더 명확하고 깔끔하게 구현 할 수 있게 해줍니다. 추가적으로 상속도 훨씬 쉽게 해줄 수 있습니다.
class Animal {
constructor(type, name, sound){
this.type = type;
this.name = name;
this.sound = sound;
}
say(){
console.log(this.sound);
}
}
const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');
dog.say();
// 멍멍
cat.say();
// 야옹
여기서 우리가 say 라는 함수를 클래스 내부에 선언하였는데, 클래스 내부의 함수를 ‘메서드’라고 부릅니다. 이렇게 메서드를 만들면 자동으로 prototype 으로 등록됩니다.
class 를 사용하면 다른 클래스를 쉽게 상속 할 수 있습니다.
class Animal {
constructor(type, name, sound){
this.type = type;
this.name = name;
this.sound = sound;
}
say(){
console.log(this.sound);
}
}
class Dog extends Animal {
constructor(name, sound){
super('개', name, sound);
}
}
class Cat extends Animal {
constructor(name, sound){
super('고양이', name, sound);
}
}
const dog = new Dog('멍멍이', '멍멍');
const cat = new Cat('야옹이', '야옹');
dog.say();
// 멍멍
cat.say();
// 야옹
상속을 할 때는 extends 키워드를 사용하며, constructor에서 사용하는 super() 함수가 상속받은 클래스의 생성자를 가르킵니다.
(이 글은 2021년 02월에 작성했던 글입니다.)