코딩기록

항해 26일) Nods.js 3-3심화주차- JS객체지향, 생성자(Constructor),prototype, class, 상속 (생활코딩) 본문

항해99/챕터3 주특기 Node.js

항해 26일) Nods.js 3-3심화주차- JS객체지향, 생성자(Constructor),prototype, class, 상속 (생활코딩)

뽀짝코딩 2022. 2. 4. 18:40
728x90

 자바스크립트는 함수형 언어

*객체란 서로 연관된 변수와 함수를 그룹핑한것. 객체 내의 변수를 프로퍼티(property=속성)라 하고 프로퍼티 안에 함수가 담겨있다면 그 함수를 메소드라 한다.

*자바스크립트는 멀티-패러다임 언어로 명령형(imperative), 함수형(functional), 프로토타입 기반(prototype-based) 객체지향 언어다. 비록 다른 객체지향 언어들과의 차이점에 대한 논쟁들이 있긴 하지만, 자바스크립트는 강력한 객체지향 프로그래밍 능력들을 지니고 있다. 간혹 클래스가 없어서 객체지향이 아니라고 생각하는 사람들도 있으나 프로토타입 기반의 객체지향 언어다.

자바스크립트는 클래스 개념이 없고 별도의 객체 생성 방법이 존재한다.

  • 객체 리터럴
  • Object() 생성자 함수
  • 생성자 함수

 

함수

*생활코딩 객체지향 15. prototype vs proto

https://www.youtube.com/watch?v=wT1Bl5uV27Y&list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3&index=26

16.4.생성자 함수를 통한 상속: constructor 속성은 무엇인가?

https://www.youtube.com/watch?v=QgVwiFoa0qU&list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3&index=30 

 


함수는 자바스크립트에서는 객체다. 그래서 프로퍼티(속성)를 가질수 있다.

 

*함수 표현 방법

1. function Person(){}

2. var Person = new Function();

 

 

person이라는 함수는

person객체고 이 객체는

person.prototype이라는 객체를 가진다.

person.prototype객체는 자신이 person의 소속이라는 표시를 constructor라는 프로퍼티를 통해 남긴다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


this

자기자신을 가리키는 단어

this는 this가 속해있는 메소드. 그 메소드가 속해있는 객체를 가르키도록 약속된 예약어.

var kim = {
    name ='kim',
    first:10,
    second:20,
    sum:function(){
        return this.first + this.second;
    }
}

console.log("kim.sum(kim.first, kim.second)", kim.sum());

//출력
kim.sum(kim.first, kim.second) 30

kim객체 안에 sum이란 메소드에 this가 있다. this를 안쓰고 kim이란 객체이름을 쓰면 나중에 kim이 k나 다른 이름으로 변경될때 마다 sum 메소드 리턴에도 변경된 이름을 써야 한다. 무엇을 가르키는지 알지만 이름을 정확히 적어야 동작하는 불편함이 있다. 그 불편함을 this가 해결해준다.

this는 this가 속한 sum메소드. 그리고 그 메소드가 속해있는 kim이란 객체를 가르킨다.

 

 

 

 

 


Constructor (생성자) 펑션

*6.3.Constructor-생성자, new Name()-객체 생성자 함수

https://www.youtube.com/watch?v=Wjrp8DHZHoo&list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3&index=10 

 

 

 

*Constructor함수는 2가지 일을 한다.

1. new Person으로 생성자 객체를 만든다.

2. this로 객체의 초기상태를 셋팅한다.

 

기존 방법

const Pak = {
    name: 'Pak'
    first:10,
    second:20,
    sum:function(){
    	return this.first + this.second;
    }
}

기존에는 중괄호{}를 통해 객체를 만들떄마다 객체를 다시 정의했지만

 

constructor(생성자)

//Constructor 펑션
function Person(name, first, second){
    this.name = name;
    this.first = first;
    this.second = second;
    this.third = third;
    this.sum = function(){
    	return this.first + this.second + this.third;
    }
}

const pak = new Person('pak', 10, 20);
const lee = new Person('lee', 10, 10);
console.log("pak.sum()", pak.sum());
console.log("lee.sum()", lee.sum());

//출력
pak.sum() 30
lee.sum() 20

constructor 펑션은 new Person() 처럼 앞에 new를 사용해서 실행할때 마다 객체가 생긴다.

또 constructor 펑션 안의 내용과 pak, lee의 인스턴스 인자 값만 바꾸면 constructor 평선을 사용하는 모든 객체가 한번에 바뀌는 편리함이 있다.

 


 

prototype

① prototype이란? 

*7.1.prototype이 필요한 이유 1:48

https://www.youtube.com/watch?v=iFiKY8kp_FU&list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3&index=12 

 

 

Person이라는 생성자가 실행이 될때마다 this(우리가 생성 하려는 객체)의 sum 이라는 이름의 함수가 생성되고 새로 만들어지고 있다. 그러면 시간과 컴퓨터 메모리가 사용되고 되고 컴퓨터의 성능이 저하된다. 

//Constructor 펑션
function Person(name, first, second){
    this.name = name;
    this.first = first;
    this.second = second;
    this.sum = function(){
    	return this.first + this.second;
    }
}

const pak = new Person('pak', 10, 20);
pak.sum = function(){
    return 'modified : ' + (this.first + this.second);
    
const lee = new Person('lee', 10, 10);
console.log("pak.sum()", pak.sum());
console.log("lee.sum()", lee.sum());

//출력
pak.sum() modified : 30
lee.sum() 20

위 처럼 pak객체가 만들어지고 sum의 동작을 바꾸려면  pak.sum = function(){~~~~} 을 매번 만들어야한다.

Person이라는 생성자를 사용하는 모든 객체의 sum 함수를 다 바꾸고 싶으면 같은 작업을 반복해야 한다. 이것이 생성자 안에서 메소드를 만드는 단점이다. 생산성이 떨어진다.

그럼 Person이라는 생성자를 이용해 만든 모든 객체가 공통으로 사용하는 (sum함수나) 프로퍼티(속성)를 만들면 얼마나 편할까?

그래서 prototype을 사용한다.

 

 

 

②  Constructor를 이용한 객체의 생성

*7.2.prototype을 이용해서 재사용성을 높이기 00:50

https://www.youtube.com/watch?v=7uL0xiFBlJI&list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3&index=12 

 

 

생성자.prototype.메서드이름 = 프로퍼티(속성)

 

Person생성자 함수에 공통으로 사용할 sum메소드를 만드는법

Person생성자함수에 sum이라는 함수의 prototype(원형)을 정한다. 

//Constructor 펑션
function Person(name, first, second){
    this.name = name;
    this.first = first;
    this.second = second;
}

//Person생성자함수에 sum이라는 함수의 prototype(원형)을 정한다. 
Person.prototype.sum = function(){
    	return 'prototype : ' + this.first + this.second;
    }

const pak = new Person('pak', 10, 20);   
const lee = new Person('lee', 10, 10);
console.log("pak.sum()", pak.sum());
console.log("lee.sum()", lee.sum());

//출력
pak.sum() prototype : 30
lee.sum() prototype : 20

차이점

아까와 달리 Person생성자 함수 안에 Person.proto~~ 정의하는 코드가 들어 있지 않기 때문에 객체가 만들어 질때 마다 정의하는 코드가 실행되지 않고 한번만 실행된다. 

Person이라는 생성자를 사용하는 모든 객체(현재는 pak, lee 두 개)가 sum함수를 공유함으로써 성능과 메모리 절약 가능하다.

 

가장 좋은것은 특정 객체만 sum 메소드 동작을 달리 만들 수 있다.

//Constructor 펑션
function Person(name, first, second){
    this.name = name;
    this.first = first;
    this.second = second;
}

//Person생성자함수에 sum이라는 함수의 prototype(원형)을 정한다. 
Person.prototype.sum = function(){
    	return 'prototype : ' + this.first + this.second;
    }

//pak객체에 Person인스턴스를 담음
const pak = new Person('pak', 10, 20);   
pak.sum = function(){
     return 'this : ' + (this.first + this.second);
}

const lee = new Person('lee', 10, 10);
console.log("pak.sum()", pak.sum());
console.log("lee.sum()", lee.sum());

//출력
pak.sum() this : 30
lee.sum() prototype : 20

이렇게 pak.sum 으로 만들고 안에 return 내용을 변경하면 pak.sum()만 변경한 내용이 나온다.

설명을 하자면,

콘솔로그에 찍은 ( pak.sum() ) pak이라는 객체에 sum이라는 메소드를 호출할 때 제일 먼저 pak 객체 자신이 sum 이라는 프로퍼티 즉, 속성이 있는지 찾는다(현재 function함수) 그래서 this~~가 출력되었다.

콘솔로그에 찍은 ( lee.sum() ) lee라는 객체는 sum메소드를 정의하지 않았다.  sum이 lee객체 자신이 갖고 있지 않으면 이 객체의 생성자인 Person의 prototype안에 sum메소드가 정의 되어 있는지 찾고 거기에 있으면 그걸 실행한다.

 

 


Class (JS만의 객체지향)

① Class란?

*8.1. Classes

https://www.youtube.com/watch?v=cmcx88U7xBE&list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3&index=13 

Constructor펑션 처럼 객체 만드는 공장

*https://caniuse.com

ES6 classes검색하면 ES6가 사용가능한 웹브라우저 확인가능하다.

*https://babeljs.io 

Try it out탭에 들어가서 왼쪽에 현재 코드(ES6버전)를 치면 오른쪽에 과거의 코드로 컨버팅 시켜서 과거 코드를 준다.

 

 

② Classes의 생성

*8.2.Classes의 생성 2:00

https://www.youtube.com/watch?v=yJNmdGlcE6s&list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3&index=14 

//Constructor 펑션
function Person(name, first, second){
    this.name = name;
    this.first = first;
    this.second = second;
}

//Person생성자함수에 sum이라는 함수의 prototype(원형)을 정한다. 
Person.prototype.sum = function(){
    	return 'prototype : ' + this.first + this.second;
    }

//pak객체에 Person인스턴스를 담음
const pak = new Person('pak', 10, 20);   
pak.sum = function(){
     return 'this : ' + (this.first + this.second);
}

const lee = new Person('lee', 10, 10);
console.log("pak.sum()", pak.sum());
console.log("lee.sum()", lee.sum());

//출력
pak.sum() this : 30
lee.sum() prototype : 20

const pak = new Person('pak', 10, 20);

Person함수 사용될때 앞에 new를 쓰면 Person함수는 객체를 리턴한다. Person함수는 constructor 펑션이 된다는뜻.

( Class에서는 Class Person으로 사용 ) 

객체가 리턴 되기전 Constructor펑션의 Person함수 안  this.~ 코드로 속성이 셋팅된 객체가 리턴된다. 즉, new Person은 그냥 함수가 아니라 생성자가 된다. 

 

 

③ Class에서 Constructor펑션 처럼 객체 만드는 방법(공장)

*9.clas의 constructor function 00:10

https://www.youtube.com/watch?v=yJNmdGlcE6s&list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3&index=14 

Class Person 의 ( Constructor펑션 ) 2가지 일

1. 객체를 생성 : new Person

2. 객체를 초기화 : this.~ 

 

class 객체에 속하는 함수를 메소드라고 한다. 

Class Person{
    constructor(){
        console.log('constructor');
    }
}

const kim = new Person();
console.log('kim', kim);

//출력
constructor
kim Person {}

자바스크립트는 new Person() 이라는 생성자가 실행되는 과정에서 constructor함수를 자동으로 실행한다. ( 강의-01:36 )

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Q1. Class는 대체로 추상화를 위해 사용됩니다. ES5 자바스크립트에서 Class는 어떻게 동작할까요?

Class= 틀, 데이터 정의만.

같은 형태 다른 데이터를 가진 객체들을 생성하기 위해 사용한다. class를 사용하면 코드의 반복을 줄일 수 있다. ES6버전(2016년 이후) 부터는 class 키워드를 통해 클라스를 선언하고 extends 키워드를 통해 상속(확장)할 수 있다. ES5버전 에서는 **생성자(constructor)**를 통해 동일한 효과를 낼 수 있다.

**생성자(constructor)**는 객체를 만드는 역할을 하는 함수다(어디에도 소속되지 않음). 자바스크립트에서 함수는 재사용 가능한 로직의 묶음이 아니라 객체의 창조자라고 할 수 있다.

  • 코드를 통한 예제
// 생성자 함수(Constructor)
1		function Person(name) {
     // 프로퍼티
2  	this.name = name;
		// 메소드
3  	this.introduce = function () {
4  		return 'My name is ' + this.name;
5  	};
6  }
		// 인스턴스의 생성
7  var p1 = new Person('egoing');
8  console.log(p1.introduce ());
9
10  var p2 = new Person('leezche');
11  console.log(p2.introduce());

번의 introduce 라는 코드가 7번, 10번 new Person(’~~’)객체가 생성될때마다 실행되어 introduce라는 메소드를 한번만 정의해도 8번과 11번이 출력될때

‘My name is egoing’

‘My name is leezche’ 가 출력 된다.

 

-코드 설명-

1번 생성자 함수 안에 7번, 10번의 person이라는 생성자가 만들어 놓은 빈 객체가 가져야 하는 프로퍼티와 메소드를 기술해 그 빈 객체가 가지고 있는 정보, 할 수 있는 일 등을 셋팅하는 것을 초기화(initialize) 라고 한다. ES6의 class전에 ES5에서는 이렇게 초기화 라는 것을 통해 코드의 재사용성을 높였다.

여기서 중요한 것은 ‘new’연산자 이다. Person이란 함수 앞에 new 연산자가 붙으면 객체 생성자가 된다. Person이란 생성자는 new로 인해 비어있는 객체를 만들고 그걸 p1, p2에 반환 한다. 생성자 함수와 new연산자를 통해 인스턴스를 생성할수 있다. 이때 생성자 함수는 클래스이자 생성자의 역할을 한다.

 

 

*생성자(constructor)는 객체를 만드는 역할을 하는 함수다(어디에도 소속되지 않음). 자바스크립트에서 함수는 재사용 가능한 로직의 묶음이 아니라 객체의 창조자라고 할 수 있다.  

 

let p = new Person();

    * Person이란 함수 앞에 new가 붙으면 객체 생성자가 된다.

    * Person이란 생성자는 new로 인해 비어있는 객체를 만들고 그걸 p에 반환한다.

    * 즉, Person함수에 new를 붙이면 그 리턴값은 객체가 된다.

 

 

 

참고

*유튜브-생활코딩- JavaScript - 생성자와 new (3/3) : 생성자와 new

https://www.youtube.com/watch?v=VnqC_EmnU9g&t=601s

* 생활코딩- prototype

https://opentutorials.org/course/743/6573

 

 

 

 

 

참고

*생활코딩-자바스크립트만

https://www.youtube.com/playlist?list=PLuHgQVnccGMAMctarDlPyv6upFUUnpSO3

 

 

 

*생활코딩-자바스크립트

https://opentutorials.org/course/743/6570

*유툽-애플코딩

https://www.youtube.com/watch?v=dHrI-_xq1Vo

*유툽-드링코딩

https://www.youtube.com/watch?v=_DLhUBWsRtw

*poiemaweb-글설명 잘되어있음

https://poiemaweb.com/js-object-oriented-programming

 

반응형
Comments