ES6 21.04.02


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);
}





© 2020.11. by creamer

Powered by CREAMer