ES6 21.04.02
in Dev on Java Script
Arrow Function
- 일반 함수 (함수 선언식 / 표현식)
// 함수 선언식
function A (name) {
return 'Hello ' + name;
}
// 함수 표현식
let A = function (name) {
return 'Hello ' + name;
}
- 화살표 함수 : 화살표 함수를 사용하면 위 함수들을 간단하게 표현할 수 있다.
let A = name => 'Hello ' + name;
// 화살표 함수를 사용하면 일반 함수의 function, return, {}, () 생략 가능.
A('creamer');
// "Hello creamer"
let B = (name, job) => 'Hello ' + name + '.' + ' Are you ' + job + '?'
// 단, 파라미터가 2개 이상인 경우 () 괄호를 사용해야한다.
B('creamer', 'developer')
// "Hello creamer. Are you developer?"
- 화살표 함수 활용 예시 : 이벤트 추가
let button = document.querySelector('button');
button.addEventListener('click', event => console.log(event));
- ex : map
// ES6 이전
let number = [1,2,3,4,5]
let numbers = number.map(function(el){
return el + '번';
});
console.log(numbers);
// ["1번", "2번", "3번", "4번", "5번"]
// ES6 : 화살표 함수 적용
let number = [1,2,3,4,5]
// return 해야 할 expression표현식;이 한줄이면 return과 중괄호{}를 생략해야한다.
let numbers = number.map(el => el + '번');
console.log(numbers);
// ["1번", "2번", "3번", "4번", "5번"]
- ex : this in arrow function arrow function에서 this를 사용하면 this는 window를 가리킨다. this를 사용하고 싶으면 arrow function을 사용하지마라.
// arrow function과 this를 사용한 경우
let CREAMer = {
name: "Terry",
age: 30,
// 실행되지 않는 함수.
addYear: () => this.age++
// 여기서 this는 window를 가리키므로 함수가 제대로 작동되지 않는다.
};
console.log(CREAMer);
// {name: "Terry", age: 30, addYear: ƒ}
CREAMer.addYear();
CREAMer.addYear();
console.log(CREAMer);
// {name: "Terry", age: 30, addYear: ƒ} // age 변화 없음.
// arrow function을 사용하지 않은 경우
let CREAMer = {
name: "Terry",
age: 30,
addYear(){
this.age++;
}
};
console.log(CREAMer);
// {name: "Terry", age: 30, addYear: ƒ}
CREAMer.addYear(); // addYear 함수가 실행되면서 age가 1 증가
CREAMer.addYear(); // addYear 함수가 실행되면서 age가 1 증가
console.log(CREAMer);
// {name: "Terry", age: 32, addYear: ƒ} //age가 30에서 32로 변경
- arrow function 실사용 사례
arrow function x find()
let emails = [
"abc@naver.com",
"def@gmail.com",
"ghi@gmail.com",
"jkl@naver.com",
"mnp@creamer.com"
];
// includes(something)는 something이 포함되어있는지 체크
let foundEmail = emails.find(el => el.includes("@gmail.com"));
// find는 함수 조건에 맞는 첫 인덱스의 요소를 찾아준다.
console.log(foundEmail);
// def@gmail.com
let number = [5, 100, 12, 8, 130, 44];
let foundNumber = number.find(el => el > 10);
console.log(foundNumber);
// 100
- arrow function x filter() : 조건을 통과한 elements로 새로운 array를 생성.
const emails = [
"abc@naver.com",
"def@gmail.com",
"ghi@gmail.com",
"jkl@naver.com",
"mnp@creamer.com"
];
const noGmail = emails.filter(argument => !argument.includes("@gmail.com"));
console.log(noGmail);
// ["abc@naver.com", "jkl@naver.com", "mnp@creamer.com"]
- arrow function x forEach() : array의 각 element 마다 제공된 function 실행 (새로운 array를 만들지는 않음)
const emails = [
"abc@naver.com",
"def@gmail.com",
"ghi@gmail.com",
"jkl@naver.com",
"mnp@creamer.com"
];
emails.forEach(argument => {
console.log(argument.split("@")[0]);
})
// abc
// def
// ghi
// jkl
// mnp
- arrow function x map() : array의 각 element 마다 제공된 function 실행하고 새로운 array 생성
const emails = [
"abc@naver.com",
"def@gmail.com",
"ghi@gmail.com",
"jkl@naver.com",
"mnp@creamer.com"
];
const emailName = emails.map(argument => argument.split("@")[0])
console.log(emailName);
// ["abc", "def", "ghi", "jkl", "mnp"]
- arrow function x Object Return
implicit return 화살표 함수(=>)를 사용하기 위해서는 바로 {}가 나오면 안된다. 때문에 ()로 감싸준다.
const emails = [
"abc@naver.com",
"def@gmail.com",
"ghi@gmail.com",
"jkl@naver.com",
"mnp@creamer.com"
];
// implicit return => 을 사용하기 위해서는 바로 {}가 나오면 안된다. 때문에 ()로 감싸준다.
let emailObj = emails.map((argument,index) => ({username: argument.split("@")[0], points: index}));
console.table(emailObj);
// index username points
// 0 "abc" 0
// 1 "def" 1
// 2 "ghi" 2
// 3 "jkl" 3
// 4 "mnp" 4
Template Literals
- backtick 사이에 넣으면 모든 문자가 string이 된다.
console.log("hello" + " World");
// hello World
console.log(`"hello" + " World"`);
// "hello" + " World"
console.log(`hello World`);
// hello World
- backtick 사이에서 변수도 실행 가능
let A = "World";
console.log(`Hello ${A}`);
// Hello World
- backtick 사이에서 함수도 실행 가능
let add = (a, b) => a + b;
console.log(`5 더하기 2는 ${add(5, 2)}이다.`)
// 5 더하기 2는 7이다.
- HTML Fragments;
// (ES6 이전) DOM을 사용하여 JS를 사용하여 HTML 설정
let addWelcome = () => {
let div = document.createElement("div");
let bigWelcome = document.createElement("h1");
let smallWelcome = document.createElement("h5");
bigWelcome.innerText = "Welcome";
bigWelcome.className = "big"
smallWelcome.innerText = "Welcome";
smallWelcome.className = "small"
div.append(bigWelcome);
div.append(smallWelcome);
};
// (E6 이후) backtick을 사용하여 HTML 구조를 만들 수 있음. (스페이스 바 인식)
let addWelcome = () => {
let div = `
<div>
<h1 class="big">Welcome</h1>
<h5 class="small">Welcome</h5>
</div>
`;
}
// 변수(파라미터) 설정, 함수 적용도 가능
let wrapper = document.querySelector("#app");
let dev = ["Front-end", "Block Chain", "EOSIO"];
let list = `
<h1>Dev Study</h1>
<ul>
${dev.map(dev => `<li>${dev}</li>`).join("")}
// map으로 배열 dev의 각 요소를 <li>에 넣어준다.
// <li>Front-end</li>,<li>Block Chain</li>,<li>EOSIO</li>
// join으로 ,를 제거한 후 string으로 만들어준다.
// <li>Front-end</li><li>Block Chain</li><li>EOSIO</li>
</ul>
`;
wrapper.innerHTML = list;
- Rule : 변수(파라미터, 인자)를 ${} 안에 넣어주고 백틱(`)으로 감싸준다.
// Template Literals 사용 전
let B = (name, job) => 'Hello ' + name + '.' + ' Are you ' + job + '?'
// "Hello creamer. Are you developer?"
// Template Literals 사용 후
let B = (name, job) => `Hello ${name}. Are you ${job}?`
// "Hello creamer. Are you developer?"
파라미터의 Default 값 설정하는 경우
let B = (name, job = 'dev') => `Hello ${name}. Are you ${job}?`
// 파라미터 job의 default 값을 'dev'로 설정
D('creamer') // "Hello creamer. Are you dev?"
// 2번째 파라미터(job)에 argument를 넣어주지 않는다면 default 값이 들어간다.
D('creamer', 'chef') // "Hello creamer. Are you chef?"
String
- 문자열.repeat(반복할 횟수)
let ID = "990101-2";
let displayID = `${ID}${"*".repeat(6)}`;
console.log(displayID);
// 990101-2******
- startsWith(), endsWith() : 시작과 끝 유효성(true / false) 검사
let ID = "990101-2";
let checkID = ID.startsWith(9);
console.log(checkID);
// true;
let ID = "090101-2";
let checkID = ID.startsWith(9);
console.log(checkID);
// false;
let email = "creamer@gmail.co.kr";
let checkEmail = email.endsWith(".com");
console.log(checkEmail);
// false
let email = "creamer@gmail.com";
let checkEmail = email.endsWith(".com");
console.log(checkEmail);
// true
Array
- Array.of(array에 넣을 elements) : Array 생성
// ES6 이전
let numbers = [1,2,3,4,5]
console.log(nubmers) // [1, 2, 3, 4, 5]
// ES6
let numbers = Array.of(1,2,3,4,5)
console.log(nubmers) // [1, 2, 3, 4, 5]
let strings = Array.of('hello');
console.log(strings) // ['hello'];
- Array.from() : 유사 배열 객체(array-like object)나 반복 가능한 객체(iterable object)를 얕게 복사해 새로운 Array 객체 생성
// string -> array
Array.from('hello'); // ["h", "e", "l", "l", "o"]
// 유사 배열 객체
function f() {
// arguments 변수명이 아니므로 반드시 arguments로 작성.
return Array.from(arguments);
}
f(1, 2, 3); // [1, 2, 3]
f('hello') // ['hello']
- 배열.find(배열의 각 요소에 적용하는 함수) : 함수를 만족하는 첫 번째 요소의 값을 반환. 요소가 없다면 undefined를 반환.
let numbers = [1, 10, 100, 1000];
numbers.find(num => num > 99); // 100
- 배열.findIndex(배열의 각 요소에 적용하는 함수) : 함수를 만족하는 배열의 첫 번째 요소에 대한 인덱스를 반환. 만족하는 요소가 없으면 -1을 반환.
let numbers = [1, 10, 100, 1000];
numbers.findIndex(num => num > 99); // 2
numbers.findIndex(num => num > 1000); // -1
- 배열.fill(값, [, 시작 인덱스, 끝 인덱스]) : 배열의 start index부터 end index의 이전까지 정적인 값 하나로 채운다. (배열을 복사하는게 아니라 배열 자체가 바뀐다.)
let numbers = [1, 10, 100, 1000];
// 값으로 배열의 인덱스 전부를 채운다.
numbers.fill(0); // [0, 0, 0, 0]
numbers.fill('a') // ["a", "a", "a", "a"]
// 배열의 1번 인덱스 부터 값으로 바꾼다.
numbers.fill('b', 1); // ["a", "b", "b", "b"]
// 배열의 2번 인덱스 부터 값으로 바꾼다.
numbers.fill('c', 2); // ["a", "b", "c", "c"]
// 배열의 3번 인덱스 부터 값으로 바꾼다.
numbers.fill('d', 3); // ["a", "b", "c", "d"]
// 배열의 0번 인덱스부터 3번인덱스 전까지 값으로 바꾼다.
numbers.fill(0, 0, 3) // [0, 0, 0, "d"]
- 배열.includes(확인할 요소) : 포함하고 있는지 체크하여 true / false로 반환
let num = [1,2,3,4,5];
console.log(num.includes(3));
// true
console.log(num.includes(6));
// false
set
어떤 타입의 unique한 value든 저장할 수 있게 해준다. (object와 비슷하지만 특별한 규칙을 가지고 있다.)
const testSet = new Set([1,2,3,3,3,4]);
console.log(testSet);
// Set(4) {1, 2, 3, 4}
// 중복된 value를 제거하고 unique한 value만 object에 담아준다.
- set.has(값) : 값을 가지고 있는지 확인
console.log(testSet.has(3));
// true
console.log(testSet.has(5));
// false
- set.delete(값) : 값 삭제
console.log(testSet.delete(3));
// Set(3) {1, 2, 4}
- set.clear() : 전부 삭제
console.log(testSet.clear());
// undefiend
console.log(testSet);
// Set(0) {0}
- set.add(값들) : 추가. 추가 시에는 각각의 값을 유니크한 값으로 보기 때문에 생략되지 않는다.
console.log(testSet.add([1,2,3,4,5,5]));
// Set(1) {Array(6)}
// [[Entries]]
// 0: Array(6)
// value: (6) [1, 2, 3, 4, 5, 5]
- Map (key value storage를 사용할 때 유용. 대부분 Set을 사용) : 객체 생성
// Map 객체 클래스 생성
const m = new Map();
// Map 객체를 참조하여 map에 key(=age)와 value(=18)을 세팅
console.log(m.set("age", 18));
// map은 object를 참조
// Map(1) {"age" => 18}
// key 값을 가지고 있는지 확인
console.log(m.has("age"));
// true
// value를 확인
console.log(m.get("age"));
// 18
// 객체 overwrite 가능
console.log(m.set("age", 30))
// Map(1) {"age" => 30}
Destructuring
Destructuring(비 구조화) : object나 array 등의 요소들 안의 변수를 밖으로 꺼내서 사용
- 객체의 key 변수 설정 후 value 사용
let obj = { a: 1, b:2 }
let { a, b } = obj;
a // 1
b // 2
- 객체 안의 객체 key 변수 설정 후 value 사용
let obj = { a: 1, b:2, c: { d: 3, e: 4 } }
let { a, b, c, c : { d }, c : { e } } = obj;
a // 1
b // 2
c // {d: 3, e: 4}
d // 3
e // 4
- 기존에 없던 객체 key-value 설정
let obj = { a: 1, b:2, c: { d: 3, e: 4 } }
let { c : {f = 5}, c : { d : { g = 6 }} } = obj;
f // 5
g // 6
- 기존에 없던 객체 생성
let obj = { a: 1, b:2, c: { d: 3, e: 4 } }
let { h : i = 9 } = obj;
i // 9
- ES6 이전 : 객체에서 직접 꺼내주기 .
const settings = {
notifications: {
follow: true,
alert: true,
unfollow: false
},
color: {
theme: "dark"
}
}
if(setting.notifications.follow) {
// send email
}
- ES6
const settings = {
notifications: {
follow: true,
alert: true,
unfollow: false
},
color: {
theme: "dark"
}
}
const {
notifications: { follow },
// = const follow = settings.notification.follow;
color,
// color 부분은 const color = settings.color; 와 같은 의미.
notifications: { comment = "기존에 없던 Object 값 넣어주기"},
// object 생성해주기
test: { text = "Text Test" } = {}
} = settings;
// settings 안에 있는 color와 notifications에 접근하여 그 안에 있는 follow를 가지고온다.
// object의 값 가져오기
console.log(follow);
// true
// object 전체 가져오기
console.log(color);
// {theme: "dark"}
// 기존 setting에 없는 object도 기본 값을 설정해서 넣어줄수 있다.
console.log(comment);
// "기존에 없던 Object 값 넣어주기"
// 기존 setting에 없는 object를 생성하고 그 안에 object를 생성하고 그 안에 기본 값을 설정해서 넣어줄수 있다
console.log(text);
// "Text Test"
- array Destructuring (가져온 정보를 조작하지 않을 때 사용하기 좋음)
// ES6 이전
let numbers = [1,2,3,4,5]
let one = numbers[0]
let two = numbers[1]
let three = numbers[4]
console.log(one, two, five);
// 1 2 5
// ES6 이후
let numbers = [1,2,3,4,5]
let [one, two, , , five] = numbers;
console.log(one, two, five);
// 1 2 5
- value 단축(key 값이랑 변수 명이 같을 때만 사용 가능)
const follow = checkFollow();
const alert = checkAlert();
const settings = {
notification: {
// follow: follow, - 이 코드를 아래와 같이 단축 가능. 값 생략
follow,
// alert: alert - 이 코드를 아래와 같이 단축 가능. 값 생략
alert
}
}
// settings라는 object 안에 notification이 있고
// 그 안에 있는 follow와 alert은
// 각각 follow = checkFollow();, alert = checkAlert();와 같다.
- variable swapping
let one = 2;
let two = 1;
one // 1
two // 2
// 변수 스왑
[one, two] = [1, 2];
one // 1
two // 2
- skipping
let numbers = [1,2,3,4,5];
// , 로 건너 뛰기 가능
let [,,, 4, 5] = numbers;
console.log(4, 5); // 4, 5
let [head, ...rest] = numbers;
head // 1
rest // [2,3,4,5]
Rest & Spread
- array spread : 변수를 array 밖으로 가져와서 나열
const numbers1 = [1,2,3,4,5];
console.log(numbers1);
// [1,2,3,4,5]
console.log(...numbers1);
// 1,2,3,4,5
// 배열 합치는 방법
const numbers2 = [6,7,8,9,0];
// 잘못된 예시 : ,가 붙지 않는다.
console.log(numbers1 + numbers2);
// 1,2,3,4,56,7,8,9,0
// 잘못된 예시 : 각 배열을 요소로 갖는다.
console.log([numbers1, numbers2]);
// [Array(5), Array(5)]
// 잘못된 예시 : 각 요소가 나열된다.
console.log(...numbers1, ...numbers2);
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 0
// 올바른 예시 : 배열 안에서 각 배열을 spread syntax로 분리
console.log([...numbers1, ...numbers2]);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
// 배열과 일반 요소 합치기
const numbers = [1,2,3,4,5]
const newNumbers = [0, ...numbers, 6];
console.log(newNumbers);
// [0, 1, 2, 3, 4, 5, 6]
const number1 = [1, 2, 3];
const number2 = [6, 7];
const numbers = [...number1, 4, 5, ...number2];
console.log(numbers);
// [1, 2, 3, 4, 5, 6, 7]
- object spread : 변수를 object 밖으로 가져와서 나열
const creamer1 = {
name: "creamer",
job: "blockcahin"
};
const creamer2 = {
age : 30,
live: "Earth"
};
// ...로 해체 후 하나의 {}에 담아주기
console.log({ ...creamer1, ...creamer2 });
// {name: "creamer", job: "blockcahin", age: 30, live: "Earth"}
// 객체와 키-값 합치기
const creamer = {
username: "creamer7"
};
console.log({...creamer, pw: 123});
// {username: "creamer7", pw: 123}
- 객체 조건
let lastName = prompt("Last name");
let user = {
username: "creamer",
age: 30,
// 조건 ? true면 실행 : false면 실행
// key : value
// (value 조건 = lastName이 공백이 아닐 경우 prompt에 입력된 lastName, 공백일 경우 undefined)
// lastName: lastName !== "" ? lastName : undefined
// 위 코드를 아래와 같이 변경 가능
...(lastName !== "" && {lastName})
// ...(lastName !== "" && lastName: lastName)
// ...(A && B) A와 B 두가지 조건이 모두 true여야만 한다.
// ... 3개의 점이 조건의 결과를 Spread
};
console.log(user);
// prompt에 lee 입력 시
// {username: "creamer", age: 30, lastName: "lee"}
// prompt에 아무것도 입력 하지 않았을 때
// {username: "creamer", age: 30}
- Rest Parameters rest는 모든 값을 하나의 변수로 축소 시켜준다.
// ...이 rest 문법
const infiniteArgs = (...r) => console.log(r);
infiniteArgs("1", 2, true, "lala", [1,3,4,5]);
// ["1", 2, true, "lala", Array(4)]
// = r
// here가 첫 인덱스, ...rest는 나머지 index
const bestNumbers = (here, ...rest) => {
console.log(`My best Number is ${here}`);
console.log(rest)
}
bestNumbers(1,2,3,4,5,6,7);
// My best Number is 1
// (6) [2, 3, 4, 5, 6, 7]
bestNumbers(7,6,5,4,3,2,1);
// My best Number is 7
// (6) [6, 5, 4, 3, 2, 1]
- destructuring + rest
const user = {
name : "terry",
age: 30,
pw: 123
};
// destructuring과 rest 동시에 사용하기
const killPw = ({pw, ...rest}) => rest;
// pw 객체(key - value) 삭제. 객체의 pw 빼고 나머지 return
killPw(user)
// {name: "terry", age: 30}
- rest + destructuring
const user = {
name : "terry",
age: 30,
pw: 123
};
// 새로운 key(=country)와 value(='korea') 추가.
// 객체 user를 spread 해주고 하나의 객체로 합쳐준다음 return
const setCountry = ({country = "Korea", ...rest}) => ({country, ...rest});
const userInfo = setCountry(user);
console.log(userInfo);
// {country: "Korea", name: "terry", age: 30, pw: 123}
- rename + destructuring + rest + spread
const user = {
a1b2c3 : "terry",
age: 30,
pw: 123
};
console.log(user);
// {a1b2c3: "terry", age: 30, pw: 123}
// a1b2c3를 name으로 바꿔주고 객체의 나머지 key-value를 합친다음 return
const rename = ({ a1b2c3: name, ...rest }) => ({name, ...rest});
console.log(rename(user));
// {name: "terry", age: 30, pw: 123}
Class
객체를 생성하기 위한 템플릿 : 객체를 위해 특정한 구조를 만들어 놓고 필요할 때마다 재활용할 수 있는 방법. (대부분 스스로 만들어 쓰진 않음 보통 라이브러이나 리액트 같은 것을 만들 때 사용)
- Class 생성 : class 표현식과 class 선언식 두 가지 방법을 제공한다. (하지만 class 선언식은 함수 선언식 처럼 호이스팅 문제를 발생시키지 않는다.) class를 사용하기 위해서는 class를 먼저 선언해야한다.
// [Class 선언식]
// class 변수명의 첫글자는 대문자로 (다른 변수들과 구분을 하기 위해)
class Human {
// constructor는 class 생성 시 필요한 데이터를 가지고 있음.
// constructor는 변수명이 아니므로 반드시 constructor로 써줘야한다.
// key 생성
constructor(Job, Age) {
// key의 값에 value 할당
this.Job = Job;
this.Age = Age;
}
}
// [Class 표현식]
let Human = class {
constructor(Job, Age) {
this.Job = Job;
this.Age = Age;
}
}
- Class 활용 : Class의 객체 생성
// 변수 = new 클래스명(클래스 파리미터1, 클래스 파리미터2)
let creamer = new Human("dev", 20);
console.log(creamer); // Human {Job: "dev", Age: 20}
let dreamer = new Human('nomad', 30);
console.log(dreamer); // Human {Job: "nomad", Age: 30}
- class x function
// class 생성
let Human = class {
// 구조 할당
constructor(Name, Job, Age) {
this.Name = Name;
this.Job = Job;
this.Age = Age;
}
// 함수 할당 (constructor 외부에 할당)
sayHello() {
console.log('Hello')
}
intro() {
console.log(`Hi my name is ${this.Name}, I'm ${this.Age} years old. I'm ${this.Job}`)
}
}
// class 활용
let terry = new Human('terry', 'dev', '30');
terry // Human {Name: "terry", Job: "dev", Age: "30"}
terry.sayHello() // Hello
terry.intro()
// Hi my name is terry, I'm 30 years old. I'm dev
- class는 원하는만큼 instance(살아있는 class)를 가질 수 있다.
class Hello {
sayHello() {
console.log("Hello");
}
}
const jsHello = new Hello();
const esHello = new Hello();
jsHello.sayHello();
// Hello
esHello.sayHello();
// Hello
- class constructor argument
// class 생성
class Hello {
constructor (name) {
// this의 key(= hi)의 value는 `Hello ${name}` 이다.
this.hi = `Hello ${name}`;
}
}
// class x argument 활용
let jsHello = new Hello('JS World');
let esHello = new Hello('ES World');
jsHello // {hi : "Hello JS World" }
jsHello.hi // "Hello JS World"
esHello // {hi : "Hello ES World" }
esHello.hi // "Hello ES World"
- class는 object 공장이다. 다수의 object를 가질 수 있다.
// class를 통해 객체를 만드는 템플릿(User) 생성
class User {
// 객체 생성 템플릿(User)은 name이라는 파라미터를 갖는다.
constructor(name) {
// 이 객체 생성 템플릿을 통해 만들어진 객체의 ket(=username)의 value는
// 파라미터의 인자로 주어진 name이다.
this.username = name;
}
// 객체 생성자에 함수도 추가
sayHi() {
// 이 객체 생성 템플릿을 통해 만들어진 객체의 key(=username)의 value(=name) 가져오기
console.log(`Hi! ${this.username}`);
}
}
// class로 만든 User 객체 생성 템플릿을 활용하여
// 각 변수에 할당
let user1 = new User('terry');
let user2 = new User('creamer');
let user3 = new User('dreamer');
// class내 함수 활용
user1.sayHi(); // Hi! terry
user2.sayHi(); // Hi! creamer
user3.sayHi(); // Hi! dreamer
sayHi();
// Uncaught ReferenceError: sayHi is not defined
// sayHi() function은 오직 class 안에서만 존재하므로 class 없이 사용 불가능하다.
- 실사용 예시
// 클래스 User 생성
class User {
// 4개의 파라미터를 가진다.
constructor (name, email, id, pw) {
// this는 이 user 클래스를 통해 만든 새로운 객체를 가리킬 것이다.
// this.키 = 값;
this.name = name;
this.email = email;
this.id = id;
this.pw = pw;
// 변수가 아니라면 파라미터에 없는 값도 할당 가능하다.
this.word = 'I Love My Life';
}
sayHi() {
console.log(`Hi, My name is ${this.name}`);
}
// this는 이 user 클래스를 통해 만든 새로운 객체를 가리킬 것이다.
getInfo() {
console.log(`${this.name}, ${this.email}, ${this.id}, ${this.pw}`)
}
// 비밀번호 바꾸는 함수. 파라미터로 새로운 비밀번호와 현재 비밀번호를 넣어준다.
updatePw(newPw, curPw) {
// 만약 현재 비밀번호가 class로 만든 비밀번호와 같다면
if (curPw === this.pw) {
// 현재 비밀번호를 새로운 비밀번호로 바꿔준다.
this.pw = newPw;
} else {// 일치 하지 않는 경우
console.log("비밀번호가 일치하지 않습니다.");
}
}
}
// class User를 통해 객체 생성
let user1 = new User('creamer', 'cream@google.co.kr', 'creamer3', '123')
// User {
// name:"creamer",
// email:"cream@google.co.kr",
// id:"creamer3",
// pw:"123",
// word: "I Love My Life";
// }
user1.getInfo();
// creamer, cream@google.co.kr, creamer3, 123
// 비밀번호 업데이트
// curPw가 다른 경우 = 실패
user1.updatePw('abc', '0') // 비밀번호가 일치하지 않습니다.
user1.pw; // '123'
// curPw가 같은 경우 = 성공
user1.updatePw('abc', '123') // undefined
user1.pw; // 'abc'
user1.getInfo();
// creamer, cream@google.co.kr, creamer3, 123
- Class extends (확장/상속) + @ : extends 키워드를 사용. 클래스 선언이나 클래스 표현식에서 다른 클래스의 자식 클래스를 생성하기 위해 사용. 다른 class의 기능 및 정보(property, function 등)를 가지고와서 적용하고 추가적인 기능 및 정보를 추가 할 수 있다.
syntax
class 자식클래스 extends 부모클래스 {
상속 받은 부모 클래스의 데이터,속성 (상속 받은 부분은 생략되어 포함된 상태)
추가할 데이터(함수, 데이터 속성 등)
}
예시 01. 상속 후 함수 추가
// intro라는 새로운 class를 만들어주고
// Human Class의 모든 데이터,속성을 상속 받는다.
class Intro extends Human {
// 아래 부분이 생략되어 포함된 상태이다.
// [Human의 모든 데이터와 속성]
// constructor(Job, Age) {
// this.Job = Job;
// this.Age = Age;
// }
// 추가할 새로운 함수, 데이터, 속성 등
sayJob() {
console.log(`my job is ${this.Job}`);
}
sayAge() {
console.log(`i'm ${this.Age} years old.`);
}
}
let terry = new Intro('dev', '30');
console.log(terry) // Intro {Job: "dev", Age: "30"}
terry.sayJob() // my job is dev
console.log(terry.sayAge()); // i'm 30 years old.
- extend 실사용 예시 : 상속 받은 class에 별도의 함수를 주어 기존 class에 없던 기능 추가
class User {
constructor(name, email, id, pw) {
this.name = name;
this.email = email;
this.id = id;
this.pw = pw;
this.word = "I Love my life";
}
sayHi() {
console.log(`Hi, My name is ${this.name}`);
}
getInfo() {
console.log(`${this.name}, ${this.email}, ${this.id}, ${this.pw}`)
}
updatePw(newPw, currentPw) {
if(currentPw === this.pw) {
this.pw = newPw
}else {
console.log("Can't change PW");
}
}
}
const creamer = new User("creamer", "creamer@email.com", "creamerid", 12345 );
// User {name: "creamer", email: "creamer@email.com", id: "creamerid", pw: 12345, word: "I Love my life"}
// Admin class는 위에서 만든 user의 모든 기능(contructor, function 등)을 가져온다.
class Admin extends User {
// user의 모든 기능이 들어간 상태 (코드 상으론 생략되어있다.)
// 새로운 함수 추가
deleteWebsite() {
console.log("deleting the whole website...");
}
}
// Admin class는 User class를 상속 받았으므로
// User의 파라미터 값인 name, email, id, pw를 작성해줘야한다.
let webAdmin = new Admin("admin", "admin@google.co.kr", "admin7", 098765);
// 상속받은 class의 함수 역시 사용 가능하다.
webAdmin.getInfo()
// admin, admin@google.co.kr, admin7, 98765
// Admin class로 생성한 객체만 가지고 있는 함수
webAdmin.deleteWebsite()
// deleting the whole website...
// 당연히 User class로 생성한 객체는 위 함수를 사용 불가능하다.
user1.deleteWebsite()
// Uncaught TypeError: user1.deleteWebsite is not a function
- class 상속의 규칙 : class를 extends하는 경우 extends하는 class에는 consructor()를 설정해주면 안된다.확장하는 class에 cuntructor를 지정할 경우 가져오는 기존의 class constructor()가 초기화(overwrite)된다.
// 연속적으로 확장 가능하다. (ex. User => Admin => Master)
// Admin Class는 User Class를 상속 받았고,
// Master Class는 Admin Class를 상속 받았다.
// 즉, Master Class는 Admin Class와 User Class의 모든 기능과 속성들을 가지고 있다.
class Master extends Admin {
constructor (superAdmin) {
this.master = superAdmin;
}
}
const mater = new Master("master", "master@email.com", "masterid", 67890);
// VM5192:3 Uncaught ReferenceError:
// Must call super constructor in derived class before accessing 'this'
// or returning from derived constructor
// 에러가 발생하는 원인은
// Class Master가 contructor를 재선언하여 기존 User의 constructor에 overwrite.
// 때문에 기존 contructor 구조로 객체를 생성 불가능하다.
// 이 문제를 해결하기 위해서는 super()를 사용해야한다.
- super(); : extends를 하면서 새로운 contructor()를 사용 할 때 발생하는 문제를 해결하는 방법.
// User Class 생성
class User {
// constructor의 property들이 너무 많아지면 헷갈리므로
// object 형식으로 변경 가능
constructor({name, email, id, pw}) {
this.name = name;
this.email = email;
this.id = id;
this.pw =pw;
}
}
// User Class를 통해 객체 생성.
let user1 = new User({
// 위 class에서 property들을 객체 안에 넣어주었으므로 객체 형식으로
name : 'terry',
email : 't77@google.co.kr',
id : 'terry7',
pw : 123
});
// User {name: "terry", email: "t77@google.co.kr", id: "terry7", pw: 123}
// User Class 확장
class Admin extends User {
constructor({ name, email, id, pw, superAdmin }) {
// super()를 사용하여 기존 User Class의 property(=key)를 불러와줄 수 있다.
super({name, email, id, pw})
// 새로운 property(=key) 추가
this.superAdmin = superAdmin;
}
}
// Admin Class를 통해 객체 생성
let admin = new Admin({
name : 'god',
email: 'godview@google.co.kr',
id: 'god7',
pw: 12345,
superAdmin: true
});
// Admin {name: "god", email: "godview@google.co.kr", id: "god7", pw: 12345, superAdmin: true}
// 확장 된 class인 Admin의 새로운 property 뿐만 아니라
// 기존 class User의 property들 또한 불러 올 수 있다.
this in class
this는 기본적으로 class 안에서 사용 할 때 class 그 자체를 가리킨다. 하지만 class와 function을 어떻게 정의하느냐에 따라 this가 가리키는 것이 달라진다.
- class ex code 1) 코드 깔끔하게 정리하기 + this
this가 항상 class를 가리키게 하려면 arrow function을 활용해라!
index1.html
<span id='count1'></span>
<button id='plus2'></button>
<button id='minus2'></button>
<script src='app.js'></script>
index2.html
<span id='count2'></span>
<button id='plus2'></button>
<button id='minus2'></button>
<script src='app.js'></script>
app.js
// Count Class 생성 (객체 만들어주기 위해)
class Counter {
// - constructor 설정
// 파라미터가 다수이므로 가독성을 위해 {} 객체 형태로 넣어준다.
// initialNumber의 default 값은 0으로 설정
constructor ( {initialNumber = 0, counterId, plusId, minusId} ) {
// this가 가리키는 것은 Counter Class를 통해 생성 된 객체
// this의 key 설정, value 할당
this.count = initialNumber;
this.count.textContent = initialNumber;
this.counter = documnet.querySelector(#counterId);
this.plusButton = document.querySelector(#plusId);
this.minusButton = document.querySelector(#minusId);
}
// - function 설정
// 이벤트 - 함수 연결
addEventListener = () => {
// this는 기본적으로 class 안에서 사용 할 때 class 그 자체를 가리킨다.
// 즉, this.increase는 class안에 있는 increase 함수를 참조한다.
this.plusButton.addEventListener('click', this.increase);
this.minusButton.addEventListener('click', this.increase);
}
increae = () => {
// 이 경우 this는 class를 가리키는 것이 아닌 element를 가리킨다.
this.count = this.count + 1;
this.diplayCount();
}
// arrow function을 사용해야 this가 class를 가리킨다.
decrese = () => {
// 이 경우 this는 class를 가리키는 것이 아닌 element를 가리킨다.
this.count = this.count - 1;
this.displayCount();
}
displayCount = () => {
this.counter.innerText = this.count;
}
}
new Counter({counterId:"count1", plusId:"plus1", minusId:"minus1"});
new Counter2({initialNumber: 1000, counterId:"count2", plusId:"plus2", minusId:"minus2"});
// class로 설계도를 만들어서 여러 곳에 적용 가능하다.
forEach vs for of vs Map
- forEach : array의 각 element 마다 function 실행. 원본 배열에 영향을 미치지 않는다.
let numbers = [1,2,3,4,5]
numbers.forEach(num => console.log(num + 1));
// 2
// 3
// 4
// 5
// 6
// 원본 배열에 영향을 미치지 않는다.
console.log(numbers); // [1,2,3,4,5]
- Map :array의 각 element 마다 function 실행하여 새로운 배열 생성
let numbers = [1,2,3,4,5]
numbers.map(num => num + 1);
// [2, 3, 4, 5, 6]
- for of : array의 각 element 마다 function 실행.
// forEach와 다른점 01 : let으로 변수 설정 가능 (const도 가능)
for (let number of numbers) {
console.log(number);
}
// forEach와 다른점 02 : forEach와는 다르게 string에서도 사용 가능. (array, lterables, NodeList 등도 사용 가능)
for (let letter of "helllloooooooo this is very loooooooooong") {
console.log(letter);
}
// forEach와 다른점 03 : loop 중에 특정 단어를 찾았을 때 멈추기 가능 (for문에서도 가능하다.)
for (let number of numbers) {
if(number === 6){
break;
}
console.log(number);
}