javascript 객체지향 (constructor, prototype, class, extend, super등등)

jangdu·2023년 3월 26일
0

javascript

목록 보기
9/16

constructor

js에서 object를 여러개 만들어야할 때 사용하는 문법인데,

var user1 = { name : 'kim', age : 10 };
var user1 = { name : 'kim', age : 10 };
var user1 = { name : 'kim', age : 10 };
var user1 = { name : 'kim', age : 10 };
...

뭐 이런식으로 수도없이 만들어야한다고 할 땐 비슷해서 막 복사하면 reference가 저장되니까 안되고,
그럴때 사용하는 문법이다.

function f() {
  this.name = 'kim';
  this.age = 10;
}
var user1 = new f();
var user2 = new f();

이렇게 하면 저 f함수안에 들어있는 name과 age가 그대로 여러개가 만들어진다.
위 코드에서 this는 새로 만들어지는 object를 뜻한다.

함수가 들어가야할 때도 마찬가지로

function f () {
  this.name = 'Kim';
  this.age = 15;
  this.sayHi = function(){
    console.log('안녕하세요' + this.name + ' 입니다');
  }
}
var user1 = new f();
var user2 = new f();

user2.sayHi();

이렇게하면 됨
걍 당연한거 ㅇㅇ

만약 오브젝트를 만들 때 그 안에 친구들 값을 정하고 싶으면?
파라미터로 전달해서 값에 넣어주면 된다.

이거보고 상속이라고한다.

prototype

js에는 constructor말고 상속기능하는 방법이 더 있다.
아까부터 만든 모든친구들에는 prototype이라는게 생성된다.

function f(){
  this.name = 'Kim';
  this.age = 15;
}
var user1 = new f();
var user2 = new f();

console.log(f.prototype);

이렇게 하면 뭔가가 출력되는데
부모의 유전자역할을 하는 친구임

이거 사용해보면

function f(){
  this.name = 'Kim';
  this.age = 15;
}
f.prototype.gender = '남'
var user1 = new f();
var user2 = new f();

console.log(f.gender);	// 남

f의 prototype에 gender : '남'이라는 데이터를 추가한 것이다.
이제부터 f를 이용해서 생성되는 모든 자식은 gender라는 속성을 사용 할 수 있다.

js에서는 object에서 data를 뽑을 때
위 코드로 예를 들어 설명하면
1. user1에 직접 gender 유무 확인
2. 부모 prototype에 확인
3. 부모의 부모에 확인
4. 부모의 부모의 부모한테 확인
....

이런식으로 내가 직적 가지고 있는지 검사 후
부모들의 prototype을 검사한다고 보면 된다.

그래서 user1이 gender라는 값이 없어도,
f.prototype에 gender가 있어서 출력이 가능하다.


array.toString()이런거도 prototype으로 쓰는거임

array, objec에는 내장함수들이 많다.
sort, push, toString, forEach, map이런거들
이런거에 .toString()이렇게 쓸 수 있는 이유는
내가 만든 array의 부모 prototype이 toString()을 가지고 있어서이다.

사실 array나 object를 만들 때는

var arr = [1, 2, 3];
var arr = new Array(1, 2, 3);

이렇게 만드는거 두줄 다 똑같은 뜻임

new Array() 즉, 우리가 array를 만들 때는
Array라는 애한테서 자식을 뽑아 새로 만든다는 거다.

그래서 Array에 생성된 자식들은 Array의 유전자에 있는
함수나 데이터를 자유롭게 사용이 가능하다.

console.log(Array.prototype);

이러면 평소에 쓰던 sort, push, toString, forEach, map 이런거들 나옴

Object 자료형 역시 똑같다.
정리하면
자식들이 값을 직접 소유하게 하려면 constructor
부모만 가지고 그걸 참조해 쓰려면 prototype
이렇게 상속하면된다.
보통은 상속할 수 있는 함수같은건 prototype으로 많이 만들어 둔다.


prototype특징

prototype은 constructor함수에만 생성

일반적인 object, array 이런거 만들어도 prototype이 없다.

그럼 일반 object같은거 상속하려면 constructor함수나, Object.create, class 같은거 써야한다.

__proto__

부모로부터 생성된 자식 ovject들은 __proto__이 속성이 있는데,
이거 출력하면 부모의 prototype이 출력된다.

function f(){
  this.name = 'Kim';
  this.age = 15;
}
var user1 = new f();
console.log(user1.__proto__);
console.log(f.prototype);

두 출력 다 똑같다.

__proto__를 직접 등록하면 object끼리 상속기능 가능

__proto__는 부모의 prototype을 의미하는데
어떤 object에 __proto__를 강제로 하나 설정하면

var 부모 = { name : 'Kim' };
var 자식 = {};

자식.__proto__ = 부모;
console.log(자식.name);

이제 자식의 __proto__다시말해서 자식의 부모는
{ name:'Kim' }이게 되는 거다.
상속기능을 이렇게도 구현 가능

Object.creat()

prototype이나 this, class도 있지만
ES5방식도 있다.
Objec.create(부모object);이렇게 쓰면 오브젝트 자료형 하나가 남는다.
그리고 부모 object가 prototype이 되는 거임

var 부모 = { name : 'Kim', age : 50 };
var 자식 = Object.create(부모);

console.log(자식.age); //50

이런식으로 쓰는데 자식 object는 부모를 prototype으로 두게된다.
자식.name, 자식.age이렇게 쓸 수 있다.

여기까지는 좀 예전 방법들이고, 요즘에는 class많이 씀


ES6 class

constructor는 오브젝트를 뽑는 기계다
ES6 class라는 신문법으로 constructor를 만들면

class Rectangle {
  constructor() {
    this.name = 'kim'
  }
}
const p = new Rectangle();

이렇게 하면된다.
function f(){}이거랑 똑같은 뜻임 ㅇㅇ
constructor()라고 쓴 부분에 this.뭐뭐 하면
새로 생성하는 오브젝트에 값을 넣을 수 있다.

상속 가능한 함수를 추가

상속이 가능한 함수를 class에 추가하는 방법은 두가지가 있다.
1. 함수를 this.f로 추가

class Rectangle {
  constructor() {
    this.name = 'kim'
    this.hi = function() { console.log('hi') }
  }
}
const p = new Rectangle();

이렇게 추가하면 새로운 자식은 hi()를 자유롭게 사용이 가능

  1. prototype에 추가
class Rectangle {
  constructor() {
    this.name = 'kim'
  }
  hi () {
    console.log('hi)
  }
}
const p = new Rectangle();

이렇게하면 p.hi()로도 된다.

Object.getPrototypeOf()

이 함수안에 오브젝트를 넣으면 부모 prototype을 출력한다.
어떤 오브젝트가 누구에게 prototype을 상속 받는지 알려준다.
__proto__이거랑 비슷함 ㅇㅇ

constructor안에 파라미터 추가

ES6방식으로 constructor에 파라미터를 추가하려면

class Rectangle {
  constructor(a, b) {
    this.name = a;
    this.age = b;
  }
}
const p = new Rectangle('park', 30);

이렇게 쓰면 됨 ㅇㅇ

extends

class Rectangle {
  constructor(name) {
    this.firstName = 'kim';
    this.name = name;
  }
}
const p = new Rectangle();

이렇게하면 새로운 object를 생성할 수 있다.
이거랑 비슷한 거 하나 더 만들때
직접 class를 하나 더 만들게되면?
코드가 너무 길어지게된다.
그럴때 extends를 쓰면 됨

이게 다른 class를 상속해서 만들 수 있게 도와줌


class Grandfather {
  constructor(name) {
    this.firstName = 'kim';
    this.name = name;
  }
}
class Father extends Grandfather {
  
}

extends는 이렇게 씀
이제 Grandfather class를 그대로 복붙한 Father이 생긴다.

new Father('du');이렇게 하면 성과 이름을 가진 object가 생성된다.

Father에 새로운 속성도 추가할 수 있고,
근데 그럴 땐 super써야함

super

class Grandfather {
  constructor(name) {
    this.firstName = 'kim';
    this.name = name;
  }
}
class Father extends Grandfather {
  constructor () {
    super(name);
    this.age = 40;
  }
}

이렇게 super를 써야만 상속받은 친구가 속성을 추가할 수 있다.
super의 의미는 extends로 상속중인 부모 class의 constructor()
즉, 위 코드에선 Grandfather의 constructor다.
이렇게 해야만 this.age를 추가할 수 있다.
근데 Grandfather constructor에 파라미터가 있으니까 그거도 super()에 명시해야만 한다.

메서드 extends

class Grandfather {
  constructor(name) {
    this.firstName = 'kim';
    this.name = name;
  }
  sayHi(){
    console.log('안녕 나는 할아버지')
  }
}
class Father extends Grandfather {
  constructor () {
    super(name);
    this.age = 40;
  }
  sayHi2() {
    super.sayHi();
    console.log('안녕 나는 아버지');
  }
}
var a = new Father('minsu');

여기서의 super는 좀 다른 의미를 가진다.
부모 class의 prototype을 의미함 ㅇㅇ

여기서 a.sayHi2()를 실행하면?
콘솔에
안녕나는 아버지
안녕나는 할아버지
이거 두개 출력됨 ㅇㅇ

profile
대충적음 전부 나만 볼래

0개의 댓글