TIL 25 | JavaScript 객체 지향 프로그래밍 02
생활코딩 객체 지향 프로그래밍 수업을 보며 정리한 내용입니다.
어제는 객체를 어떻게 만들고 어떻게 쓸 수 있는지를 배웠다. 이제 객체에 대해 이해한것을 바탕으로 조금 더 심화된 내용을 공부해보려고 한다!
1. constructor
1-1. constructor의 필요성
전에 만들었던 것처럼 그냥 객체를 만들어보면,
const kim = {
name: "kim",
first: 10,
second: 20,
sum: function () {
return this.first + this.second;
},
};
const lee = { //다른사람을 또 하나 만들어본다.
name: "lee",
first: 10,
second: 10,
sum: function () {
return this.first + this.second;
},
};
console.log(kim.sum()); //30
console.log(lee.sum()); //20
→ 아쉬운 점 : 만약 객체가 동작하는 방법이 바뀌어서(예_ third가 추가된다면) 수정해야 한다면, 이것뿐만 아니라 또 같은 형태의 객체들 모두에게 적용해주어야 한다. 만약 이런 작업을 1억개에게 해줘야 한다면,,? 🤦🏻♀️
const kim = {
name: "kim",
first: 10,
second: 20,
third: 30, //여기도 추가해주고
sum: function () {
return this.first + this.second + this.third; //여기도 추가해주고
},
};
const lee = {
name: "lee",
first: 10,
second: 10,
third: 10, //여기도 추가해주고
sum: function () {
return this.first + this.second + this.third; //여기도 추가해주고
},
};
console.log(kim.sum()); //60
console.log(lee.sum()); //30
→ 즉, 이렇게 객체의 기본 동작방법이 바뀐다면 같은 취지의 객체는 이렇게 다~~~ 바꿔줘야 한다는 것이다.
👏🏻 그렇기 때문에 이런 형식의 객체를 찍어내는 공장(constructor)을 만들거고, 이제 그 공장을 이용해서 객체를 양산해보자!! ✨
1-2. constructor의 사례
- JavaScript에는 시간을 알아내고 싶을 때 사용하는
Date
라는 것이 있다. - 그리고 이
Date
를 이용할때에는 new 라는 키워드를 붙여주고 - 그리고 이
Date
의 (괄호) 안에다가 현재날짜를 적어준다. - 그다음 d1 이라고 하게되면은
=> 내부적으로 2020년 12월 28일이라고 하는 데이터를(상태를) 가지고 있는 새로운 객체가 만들어져서 d1이 된다. - (비교) 위에서 우리가 만든 const lee, const kim 은 객체의 설계도가 다 노출이 되는데
- Date( ) 를 보면 이걸 통해 최종적으로 만들어진 객체가 어떤 설계도를 가지고 있는지 우리 눈엔 보이지 않는다.
- 하지만 그럼에도 우린 d1 이라는 객체를 사용할 수 있다.
const d1 = new Date("2020-12-28");
console.log(d1.getFullYear()); //그 객체에게 연도를 물어본거다. ... 2020
console.log(d1.getMonth());// 11 이 나오는데 ... month는 0부터 count 되기 때문이다.
const d1 = new Date("2020-12-28");
← 이걸 보면 함수를 호출하는 것처럼 보이죠? 👀 .. 맞다! 왜냐하면 저 Date가 함수이기 때문이다!
console.log(Date);
를 출력해보면 아래사진처럼 나오는데, 풀이를 해보면 ... Date는 함수고, native code라는건 내장된 함수라는 뜻이다.
1-3. constructor 만들기
이제 그럼, Date
처럼 객체를 찍어내는 공장을 만들어보자 🙂
function Person() {
this.name = "kim";
this.first = 10;
this.second = 20;
this.third = 30;
this.sum = function () {
return this.first + this.second + this.third;
};
}
→ 그리고 방금 만든 Person
이라는 함수를 직접 호출해보자!
console.log(Person()); //undefined
🤔 왜 undefined
가 나올까? => 왜냐하면 Person
함수는 아무것도 return하고 있지 않기 때문이다.
🤚🏻 그런데 Person
앞에다가 new
라는 키워드를 붙여보게 되면? 이제 Person
이라는 함수는 완전히 다른 존재가 된다!
console.log(new Person()); //Person {name: "kim", first: 10, second: 20, third: 30, sum: f}
→ 결과는 Person 이라는 객체가 만들어졌다! .. 이객체의 속성은 name은 kim, first는 10 .... sum이라는 함수까지!
- 정리해보면 함수를 그냥 호출하면 그건 그냥 함수이다.
- 그런데 앞에
new
라는 키워드를 붙이면 이제 이 함수는 더이상 일반적인 함수가 아니라!! - 객체를 생성하는 생성자가 되는 것이다!!! 그럼 생성자가 영어로는? constructor!
- 그러니까 new Person( )처럼 앞에
new
가 붙어있으면! 맥락적으로 얘를 생성자함수라고 부른다는 것도 기억하자!
그럼 이제 어떻게 변화하는지 한번 보자!
const kim2 = new Person();
const lee2 = new Person();
그리고 실행했을때 어떻게 되는지도 확인해보자!
console.log(kim2.sum()); //60
console.log(lee2.sum()); //60
🤔 ... 둘 다 60이 나오는데, 그 이유는 뭘까?
→ kim2에 있는 new Person이나, lee2 에 있는 new Person 모두가 내부적으로 같은 상태 를 가지고 있어서 그렇다.
👏🏻 그럼 이제 난 뭘 하고 싶을까?
Date 객체처럼 (const d1 = new Date("2020-12-28");
),
constructor 함수가 실행될 때 입력값을 주입할 수 있던 것과 같이 우리도 할 수 있다! 그걸 해보자!
function Person3(name, first, second, third) {
this.name = name;
this.first = first;
this.second = second;
this.third = third;
this.sum = function () {
return this.first + this.second + this.third;
};
}
const kim3 = new Person3("kim", 10, 20, 30);
const lee3 = new Person3("lee", 10, 10, 10);
console.log(kim3.sum()); //60
console.log(lee3.sum()); //30
이게 바로 객체를 찍어내는 공장인 constructor function 을 만들어내는 방법이다. ✨
😇✨ 그래서 이 constructor function
을 만들어서 생기는 좋은점은!
- 이전에는 중괄호를 통해서 객체를 만들때마다 그 객체를 다시 정의해줬어야 했는데
const kim = {
name: "kim";
first: 10;
second: 20;
sum: function () {
return this.first + this.second;
};
}; //.. 이렇게
- 이제 우리가 이
constructor function
을 만들게되면, 앞에new
를 사용함으로써.. 실행할 때마다 객체가 양산된다. - 그리고!
constructor function
의 내용을 바꾸면 이constructor function
을 사용해 만들어진 모든 객체가 한.번.에 바뀌는 폭발적인 효과를 얻게된다. 🥳 🎉
그럼 이제 constructor function이 무언인지 / constructor function 을 쓰면 뭐가 좋은지 를 알게 되었다! 🙂
2. prototype
prototype 은 한국어로는 '원형' 으로 번역될 수 있는 말이다. 어떤 사물의 공통된 모습? 또는 본래의 모습?
자바스크립트에서 prototype 이라는 것은? JavaScript을 object-oriented language(객체지향언어) 라고 했듯이 또 prototype based language (프로토타입 기반 언어) 라고도 한다. 이렇게 불리듯! 그만큼 프로토타입이라는 것은 자바스크립트를 지탱하는 기반이라고 할 수 있다.
2-1. prototype이 필요한 이유
function Person(name, first, second, third) { //Person이라고 하는 함수가 이거 *
this.name = name;
this.first = first;
this.second = second;
this.third = third;
this.sum = function () {
return this.first + this.second + this.third;
};
}
const kim = new Person("kim", 10, 20, 30); //kim이라는 객체를 생성하는게 이거 *
const lee = new Person("lee", 10, 10, 10);
constructor function
을 이용해서 여기까지 잘 만들어봤지만 그래도 아직 아쉬운 부분이 있다.
지금 보면 kim이라는 객체∗ 를 생성할 때 Person이라고 하는 함수∗ 를 생성자로써 동작시켰다. 그런데 이 생성자 함수 안에 this.sum 이라는 함수가 들어있기 때문에 객체가 생성될 때마다 계속 함께 만들어져 실행 되므로 컴퓨터 메모리가 낭비된다. 뿐만 아니라 만약 극단적으로 엄청 많은 객체를 생성한다고 가정하면, 이 함수를 생성하는데에도 많은 시간이 소요가 될 것이고 이건 성능을 저하시키는 요소가 될 수 있다.
🚨 그렇기 때문에 이 부분을 수정해야 한다!
2-2. prototype을 이용해서 재사용성 높이기
프로토타입 이라는 개념을 이용해서 생성자를 통해 만든 객체들 모두가 공통적으로 사용하는 속성을 만드는 방법을 배워보자.
✨ 생성자 함수에서 공통적으로 사용할 method를, prototype
을 이용해 따로 빼서 만들어준다.
function Person(name, first, second, third) {
this.name = name;
this.first = first;
this.second = second;
this.third = third;
}
//Person이라는 생성자 함수에 공통적으로 사용할 sum이라는 method를 이렇게 만든다!
Person.prototype.sum = function () {
//그럼 여기안에서 수정해도 Person을 통해 만든 객체 전부에게 적용된다.
return this.first + this.second + this.third ;
};
// 출력해보면,
const kim = new Person("kim", 10, 20, 30);
const lee = new Person("lee", 10, 10, 10);
console.log(kim.sum()); //60
console.log(lee.sum()); //30
→ 출력되는 결과는 같지만! 이렇게 하면 차이점이 있다.
- Person이라는 생성자 함수(constructor) 안에 sum을 정의한 것이 들어가 있지 않기 때문에 객체가 만들어질 때마다 실행되지 않고 한번 실행된다.
: 그럼 한번만 정의되는 것이기 때문에 성능과 메모리를 절약할 수 있다. - 그리고 하나의 함수를 수많은 객체들이 share할 수 있다. (prototype을 이용해 만든 함수 한곳에서만 수정해도 전부 적용된다.)
: 이를 통해서도 역시 성능과 메모리를 절약할 수 있다.
✨ 같이 만들어진 수많은 객체들중에서 하나의 객체의 method만 수정하는 것도 가능하다!
kim.sum = function () {
return "this method has changed!";
};
console.log(kim.sum()); //this method has changed!
console.log(lee.sum()); //30
🤔 이렇게 변수 kim이 가리키는 객체의 sum method만 다르게 동작시킬 수 있는 이유는? (프로토타입의 특징이다.)
→ 자바스크립트는 kim이라는 객체의 sum 메소드를(kim.sum()
) 호출 할 때 제일 먼저 그 객체 자신이 sum 이라고 하는 속성을 가지고 있는지를 찾는다. (= 그 속성이 지금 여기에선 함수) 그렇기 때문에 kim.sum = function () { return "this method has changed!"; };
을 실행을 시키고, 거기서 끝을 내는거다.
그런데 lee라고 하는 객체는, 이 객체를 생성const lee = new Person("lee", 10, 10, 10);
한 이후에 sum이라는 어떤 method를 정의한 적이 없기때문에! JavaScript는 우리가 찾는 이 sum을(lee.sum()
) lee라고 하는 객체 자신이 가지고 있지 않으면 이 객체 생성자인 Person의 prototype이라고 하는 것의 sum이라고 하는 method가 정의되어 있는지 찾고, 그게 찾아지면 그걸 실행하는 것이다.
이제 이 질문들에 대답할 수 있다 🙂
- 프로토타입이란 어떤 의미가 있는지
- 우리가 프로토타입을 사용하지 않고 이 생성자 함수 안에서 method 나 속성을 직접 정의하게 되면 어떤 비효율이 생기는지
- 그러면 그 비효율을 프로토타입을 통해서 어떻게 극복했는지
Author And Source
이 문제에 관하여(TIL 25 | JavaScript 객체 지향 프로그래밍 02), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@saemsol/TIL-25저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)