[230419] 객체지향 프로그래밍

윤지수·2023년 4월 19일
0
post-thumbnail

🪄 객체지향 프로그래밍

프로그램을 작성할 때 객체들을 만들어 서로 상호작용하도록 하는 방법
객체 지향의 객체: 표현하고자 하는 사물을 추상적으로 표현한 것
추상화란 필요한 최소한의 정보로 대상을 표현하는 것

생성자(constructor)

객체를 만들 때 new 연산자와 함께 사용하는 함수

생성자를 통해 생성된 객체는 같은 프로퍼티와 메서드를 공유할 수 있다.
복사, 붙여넣기를 안해도 똑같은 프로퍼티와 메서드를 가진 객체를 여러 개 생성할 수 있다.

생성자 함수는 암묵적으로 대문자로 시작하는 이름을 가지는 것으로 약속되어 있다.
new 키워드를 통해 객체를 생성한다. 이때 반환되어 만들어진 객체를 다른 말로 인스턴스(instance)라고 한다.
사용자정의 타입이란 원시타입과 참조타입처럼 사용자가 직접 만든 생성자를 통해 생성된 인스턴스를 의미한다.

function Factory() {
    this.name = name;
    this.sayYourName = function() {
        console.log(`삐리비리. 제 이름은 ${this.name}입니다.`);
    }
}

let result1 = Factory();
console.log(result1);	// undefined

let result2 = new Factory('말랑');
console.log(result2);	// Factory {name: '말랑', sayYourName: ƒ}

Factory를 단순히 함수로 실행하면 반환값(return)이 없기 때문에 undefined만 반환된다.
Factory 함수는 new 키워드가 앞에 붙게 되면 실행되었을 때 자동적으로 객체(인스턴스)를 생성하고 반환한다.

원래 함수 안에서의 this는 함수를 호출한 객체를 참조한다. 하지만 생성자 함수 앞에 new 연산자가 사용되면 함수 안의 this는 생성자가 만들어낸 객체 즉, 인스턴스를 참조한다.

=> 생성자는 필요에 따라서 배열(Array), 객체(Object)를 사용하는 것처럼 필요할 때 사용할 수 있는 우리만의 객체를 만들어서 사용할 수 있도록 도와준다.

프로토타입

객체를 생성할 때마다 새로운 함수를 생성하고 있는 문제가 있다.

this.sayYourName = function() {
    console.log(`삐리비리. 제 이름은 ${this.name}입니다.`);
}

자원의 낭비를 해결하기 위해 등장한 것이 프로토타입이다.

function Factory(){
    this.name = name;
}

Factory.prototype.sayYourName = function() {
	console.log(`삐리비리. 제 이름은 ${this.name}입니다.`);
}

프로토타입은 특정 객체에 대한 참조. 어떠한 공간을 가르키고 있다.
생성자 함수가 인스턴스를 생성하게 되면 그 안에는 숨겨진 프로퍼티인 [[Prototype]]이 존재하게 된다. 코드상에서는 __proto__로 표현된다. __proto__ 프로퍼티는 자신을 만든 생성자 함수의 prototype을 참조하는 역할을 한다. 즉, new 키워드를 통해 생성자 함수의 prototype 프로퍼티와 인스턴스의 __proto__ 프로퍼티가 연결된다.

💡 prototype__proto__
prototype은 오직 function 안에 존재하는 참조값
__proto__는 객체 안에 존재하는 숨겨진 프로퍼티
인스턴스는 __proto__ 프로퍼티를 통해 생성자 함수의 prototype 프로퍼티에 접근하여 필요한 여러가지 값과 메서드를 사용할 수 있다.

function Test(){};

const obj = new Test();

console.log(obj.prototype); 					// undefined
console.log(obj.__proto__ === Test.prototype);  // true 

=> 프로토타입은 모든 인스턴스가 하나의 프로퍼티나 메서드를 공유하도록 만들어 자원을 더 효율적으로 사용하도록 도와준다.

객체의 상속

const obj = {
  name: 'test'
}

console.log(obj.hasOwnProperty('name'));	// true

const arr = [1,2,3];

console.log(arr.hasOwnProperty('name'));	// false

Q. 배열에 hasOwnProperty 메소드를 사용할 수 있나?!
A: 🙆🏻‍♀️
arr의 __proto__가 Array 함수의 prototype를 참조하고, Array 함수의 __proto__가 Object 함수의 __proto__를 참조하고 있기 때문에 Array 함수의 prototype에 존재하지 않는 Object 객체의 프로퍼티와 메서드를 사용할 수 있다.
자기 자신에게 존재하지 않는 프로퍼티나 메서드를 프로토타입을 통해 추적하는 과정을 프로토타입 체이닝이라고 한다.

💡 자바스크립트의 타입들은 기본적으로 Object 타입을 상속받고 있다.

console.log(Array.prototype.__proto__ === Object.prototype);
console.log(Number.prototype.__proto__ === Object.prototype);
console.log(String.prototype.__proto__ === Object.prototype);
console.log(Math.__proto__ === Object.prototype);

직접 생성한 생성자 함수 상속

function Parent() {
    this.name = '재현';
}
Parent.prototype.rename = function (name) {
    this.name = name;
}
Parent.prototype.sayName = function () {
    console.log(this.name);
}

function Child() {
    Parent.call(this);
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.canWalk = function () {
    console.log('now i can walk!!');
}

class

클래스의 결과물은 인스턴스 생성
클래스는 붕어빵의 틀, 인스턴스는 붕어빵

생성자를 이용한 타입 생성과 그 결과가 정확하게 일치한다.
자바스크립트만의 사용자정의 타입 생성(객체 생성) 방법을 다른 언어의 클래스 문법처럼 바꿔준 것이다.

class Robot {
    // 클래스의 생성자 함수
  	// 하나의 클래스는 하나의 생성자만 정의할 수 있다
	// 생성자 함수는 new 키워드가 호출될때 자동으로 실행된다
    constructor(name) {
        this.name = name;
    }

    // 메소드 정의
  	// 메소드는 클래스가 생성한 인스턴스를 통해 사용할 수 있다
    sayYourName() {
        console.log(`삐리비리. 제 이름은 ${this.name}입니다.`);
    }
}

0개의 댓글