18.Constructure, Prototype, class (객체지향) - ES6
Updated:
Constructor
Constructor 용도
- object 를 쉽게 복사 할 수 있을때 사용합니다.
// constructure 생성 보통 생성 자 이름에 대문자를 사용해서 일반 함수와 다르다는것을 구분하기 위해 처음 글자를 대문자를 넣어서 사용함
function Student(name, age) {
this.name = name; // this 는 새로 생성되는 object 를 뜻함
this.age = age;
this.sayHi = function () {
console.log(`안녕하세요 ${this.name} 입니다` )
}
}
// this.age =15 이렇게 새로 생성되는 object 에 값을 부여 가능
const student1 = new Student('Park', 30) // constructure 를 복사해서 뽑아 내는것
const student2 = new Student('Kim', 20) // constructure 를 복사해서 뽑아 내는것
console.log(student1)
console.log(student2)
student1.sayHi();
Constructor 연습
🔷 쇼핑몰에서 쓸 상품데이터를 object 형태로 여러개 만들고 싶을경우 와 tax()
라는 함수가 실행 될때 10% 만큼 부가세가 출력 되게 만들고 싶을 경우의 consructure 생성
function Product(name, price) {
this.name = name, // 주로 책에서 this 생성자를 instance 라고 합니다
this.price = price,
this.tax = function () {
console.log(this.price * 0.1)
}
}
const product1 = new Product('shirts', '50000')
const product2 = new Product('pants', '60000')
console.log(product1)
console.log(product2)
product1.tax()
- 위의 constructure 를 활용해서 여러 object 를 만드는 것을 상속 (inheritance) 라고 말함
Prototype
-
JS 에 만 있는 상속을 구형 할 수 있는 또 하나의 문법인 prototype 입니다
-
protopype 은 유전자 라고 생각하면 됩니다.
-
constructor 를 만들면 prototype 이라는 공간이 자동으로 생깁니다.
-
prototype 에 값을 추가 하면 모든 자식들이 물려 받기가 가능합니다.
function Product(name, price) {
this.name = name,
this.price = price,
this.tax = function () {
console.log(this.price * 0.1)
}
}
const product1 = new Product('shirts', '50000')
const product2 = new Product('pants', '60000')
Product.prototype.color = 'red'; // 부모인 Product 에 color 라는 key 값을 등록을 하게 되면 그 constructor 를 사용하는 자식 object 들은 그것을 다 상속을 받습니다.
console.log(product1.color) // 위에 constructro 에 prototype 으로 유전자를 color 라는것을 썼기 때문에 color 값이 출력 할 수 있음
Prototype 동작원리
-
위의 code 에서
product1.color
을 실행하게 되면 JS 의 해석은 다음 순서와 같습니다.-
product1이 직접 color 을 가지고 있는가?
-
있으면 출력하는데, 만약 없다고 하면 product1의 부모 유전자가 color 를 가지고 있는가? 를 검사 함
-
부모 유전자에 있는게 color 가 있는 게 확인이 되면 그것을 출력함
-
Prototype 내장 함수 동작
-
위의 code 에서
product1.toString()
인 JS 내장 함수를 사용하게 되면 을 JS 의 해석은 다음 순서와 같습니다.-
product1 이 toStrin() 을 가지고 있는가?
-
없다면 부모 유전자에는 있는가?
-
없다면 부모의 부모 유전자에 있는가?
-
product1.toString()
const arr = [1, 2, 3]; // 사용자 측면에서 arr 생성
const arr = new Array(1, 2, 3) // 실제 JS 가 내부적으로 array 가 만들어지는 방식임
const obj = { name : 'kim' };
const obj = new Object();
Array.prototype; // Array prototype 에 있는지 확인을 함
arr.sort(); // Array 에 prototype 이 포함되어 있는 것을 사용할 수 있음
🔑 그럼 prototype으로 상속시키는거랑 constructor로 상속시키는거랑 차이가 뭐죠?
-
자식들이 값을 직접 소유하게 만들고 싶으면 constructor로 상속시키시면 되고
-
부모만 가지고 있고 그걸 참조해서 쓰게 만들고 싶으면 prototype으로 상속시키면 됩니다?
-
보통은 그래서 상속할 수 있는 함수 같은 것들은 prototype으로 많이 만들어놓습니다.
Prototype 특징
1.Prototype 은 함수에만 생성됩니다.
-
일반 object, array 이런거 만들어도 거기엔 prototype이 없습니다.
-
그럼 일반 object 같은걸 상속하고 싶으면 어떻게 할까요?
-
constructor 함수를 만들던가.
-
Object.create() 를 만들어서 쓰던가.
-
class를 만들어 쓰면 됩니다.
-
2.내 부모 유전자(부모의 prototype)을 검사하고 싶다면 proto
-
부모로부터 생성된 자식 object들은
__proto__
라는 속성이 있습니다. -
이걸 출력해보시면 부모의 prototype이 출력됩니다.
-
그래서
__proto__
는 부모의 prototype과 같은 의미입니다.
function Student(){
this.name = 'Kim';
this.age = 15;
}
var student1 = new Student();
console.log(student1.__proto__);
console.log(Student.prototype);
3.__proto__를 직접 등록하면 object 끼리 상속기능을 구현가능합니다.
const parent = { name : 'Kim' };
const child = {};
child.__proto__ = parent; // child 에 parnet 에 등록해서 사용함
console.log(child.name); // Kim 출력
4.콘솔창에 prototype 정보들이 항상 출력됩니다.
function Students(){
this.name = 'Kim';
this.age = 15;
}
Students.prototype.gender = 'male';
let student1 = new Students();
console.log(student1)
-
이렇게 쭉 내 부모의 부모까지 탐색할 수도 있습니다.
-
탐색해보시면 모든 object 자료형의 조상은 Object() 라는 Student 이며 (일명 Object.prototype)
모든 array 자료형의 조상도 Object()입니다. (중간에 Array()라는 부모도 있고요)
모든 함수 자료형의 조상도 Object() 입니다.
(그래서 자바스크립트는 모든게 다 Object라고 말하는 것입니다.)
Constructure, prototype 연습
Q1. object 를 여러개 만들기
-
student1,2,3 을 constructure 를 사용해서 출력하기
-
constructure 안에
sayHi()
라는 함수를 실행해서 메세지 출력
function Student(name, age) {
this.name = name,
this.age = age,
this.sayHi = function () {
console.log(`안녕 나는 ${this.name}이야`)
}
}
const student1 = new Student('kim', 20)
const student2 = new Student('park', 21)
const student3 = new Student('Lee', 22)
console.log(student1)
console.log(student2)
console.log(student3)
student1.sayHi();
Q2. array 안에서 특정 숫자 제거하는 함수 만들기
- 모든 array 에 사용되고, array 내에 3이라는 값을 제거하는 함수를 만들어 보자
let arr = [1, 2, 3]
Array.prototype.remove3 = function () { // remove3 이라는 array 내장함수 같이 prototype 형식으로 Array object 에 함수를 만들어서 넣기임
for (let i = 0; i < this.length; i++){ // arr 길이 만큼 탐색 (0번 index 부터 니까 this.length 만큼만 반복)
if (this[i] === 3) {
this.splice(i, 1) // 만약 3을 발경하면 그자리 index 번호의 뒤에 1개를 splice 제거 해주는것임
}
}
}
arr.remove3()
console.log(arr) // 1, 2 가 출력 됨
Object.create() - ES5
- prototype 을 대신해서 상속기능을 사용할 수 있는 ES5 버전의
object.create()
을 사용하는 방법 입니다.
// Object.create(prototype object);
let parent = {
name: 'kim',
age: 50
}
// 부모가 가진 name, age를 그대로 물려받은 object 를 만들고 싶으면?
// 1. constructor 함수를 만들거나.
// 2. Object.create() 을 사용하거나
let child = Object.create(parent); // 이거는 그냥 prototype 을 부모로 해주세요 라는 의미만 됨
console.log(child)
console.log(child.name) // kim 으로 출력됨
// 왜냐하면 1. 자식에 name을 직접 갖고 있나 X => 없으면 자식의 부모 prototype에는 name 이 있나? O 있으니까 kim 이 출력되는 것임
// 자식을 바꾸고 싶으면
child.age = 20
console.log(child.age); // 20 출력
// 자식의 자식도 만들 수 있음
let son = Object.create(child)
console.log(son.age) // 바로 위의 child 의 age를 출력 할 수 있음
Class - ES6
// constructor 만드는 신문법
// 함수를 추가 하고 싶으면 1. constructor 에 추가를 하던가
class parent {
constructor() {
this.name = 'kim'
this.sayHi = function () {
console.log('hello')
}
}
saybye() { // 함수 추가 하시면 2. 요기에다가 쓰던가. 단!! 여기에 쓰면 자식 object 에 추가가 안됨 부모.prototype 에 추가됨
console.log('bye')
}
}
let child = new parent()
console.log(child)
// Q. child.__proto__ 의 경우는 ?
// A.
console.log(child.__proto__)
console.log(parent.prototype)
console.log(Object.getPrototypeOf(child))
extends / super
// 아래의 parent class 유사한 class 를 하나 더 만드는것 extends (class 상속)
class parent {
constructor(name, name2) {
this.firstname = 'kim';
this.lastname = name;
this.nickname = name2;
}
// super()의 또 다른 용도
sayHi() {
console.log('Hi');
}
}
let parent1 = new parent('jacob', 'test') // 기존의 class 복사를 통해서 만든것
console.log(parent1)
// 복사 / 상속 할 값이 많으면 힘들기 때문에 extends 로 class 를 복사해서 사용합니다
// parent 의 속성들을 그대로 물려 받아서 사용하려면
class father extends parent {
constructor(name, name2) {
// super()의 의미는 parent 의 constructor를 복사해서 같다 쓰는것과 같음
super(name, name2); // super 를 사용해야 this 를 사용할 수 있음
this.age = 50; // extends 해서 만든 class는 this 그냥은 못씁니다
}
sayBye() {
console.log('Bye');
super.sayHi(); // 여기서 super() 는 부모 class 의 prototype 을 의미함
}
}
let father1 = new father('John', 'test2');
console.log(father1)
console.log(father1.sayHi())
getter / setter
- get / set 없이 object 만들기
let person = {
name: 'Park',
age: 30,
nextAge() { // 내년도의 알기 위한 function
return this.age + 1;
},
setAge(age) {
this.age = parseInt(age); // 정수로 변환 되기 때문에 str 이 들어와도 number 로 바꿔줌
}
}
// age 라는 자료를 꺼내고 싶으면?
console.log(person.age) // 이렇게 직접 데이터를 꺼내서 사용시에는 수정할 때 실수가 유발 될 수 있음
// 다른 방법으로 요즘 유행하는 자료를 꺼내는 법은?
// 함수를 만들어서 object 데어터를 다루는 이유는 ?
// 1. object 자료가 복잡할 때 이득
// 2. object 자료 수정시..
// 즉, 데이터를 꺼내거나 / 수정하거나 그럴때 편리 & 실수 방지 & 관리 가능
console.log(person.nextAge())
person.setAge(20); // 20으로 변경
console.log(person.age)
- ES5 부터 set /get 키워드가 실행되서 더 간단히 위에 코드를 만들 수 있음
let person2 = {
name: 'Park',
age: 30,
get nextAge() { // 데이터를 꺼내 쓰는 함수에 사용
return this.age + 1;
},
set setAge(age) { // set 은 데이터 변경하는 함수에 사용
this.age = parseInst(age); // 정수로 변환 되기 때문에 str 이 들어와도 number 로 바꿔줌
}
}
// 이렇게 사용하게 되면, 괄호를 안해도 아래와 같이 간단하게 사용할 수 있음
person.setAge = 20;
// get 을 사용했기 때문에
console.log(person2.nextAge) // 31 출력
getter, setter 주의점
- getter 는 return 이 있어야 합니다.
- setter 는 parameter 가 1개 있어야 합니다.
class 에서 사용하는 get / set
class person {
constructor() {
this.name = 'Park';
this.age = 20;
}
get nextAge() {
return this.age + 1
}
set SetAge(age) {
this.age = age;
}
}
let person1 = new person();
console.log(person1)
console.log(person1.nextAge) // 괄호를 사용하지 않아도 get 을 사용했기 때문에 안써도 됨
person1.SetAge = 80; // set 함수를 통해서 80으로 값을 변경 한것임
console.log(person1)
연습문제 (class, extends, getter, setter)
Q1. class 를 사용하여 유사 object 를 만들기
class dog {
constructor(type, color) {
this.type = type;
this.color = color;
}
}
let dog1 = new dog('말티즈', 'white')
let dog2 = new dog('진돗개', 'brown')
console.log(dog1)
console.log(dog2)
Q2. 위의 코드에서 extends 를 사용해서 age 타입 추가 하기
class Cat {
constructor(type, color) {
this.type = type;
this.color = color
}
}
class CatAge extends Cat {
constructor(type, color, age) {
super(type, color);
this.age = age;
}
}
const cat1 = new CatAge('코숏', 'white', 5)
const cat2 = new CatAge('러시안블루', 'brown', 2)
console.log(cat1)
Q3. get / set 을 사용해서 게임 Unit 만들기
-
조건
-
모든 Unit의 인스턴스는 공격력, 체력 속성이 있으며 기본 공격력은 5, 기본 체력은 100으로 설정되어 있어야 합니다.
-
모든 Unit의 인스턴스는 전투력을 측정해주는 battlePoint라는 getter가 있습니다. console.log( 인스턴스.battlePoint ) 이렇게 사용하면 현재 공격력과 체력을 더한 값을 콘솔창에 출력해주어야합니다.
-
모든 Unit의 인스턴스는 heal이라는 setter가 있습니다. 인스턴스.heal = 50 이렇게 사용하면 체력 속성이 50 증가해야합니다.
-
class Unit {
constructor() {
this.str = 5;
this.con = 100;
}
get bettlePoint() {
return this.str + this.con;
}
set heal(a) {
this.con = this.con + a;
}
}
const unit1 = new Unit();
console.log(unit1.bettlePoint);
unit1.heal = 50;
🔶 🔷 📌 🔑
Leave a comment