[TIL - 2021.7.22 객체지향 프로그래밍]

Jeong Ha Seung·2022년 7월 22일
0

부트캠프

목록 보기
20/51

오늘 배운 내용

  1. 클래스와 인스턴스

    • 클래스란 무엇인가?
      • 객체(인스턴스)를 만들기 위한 설계도다. 이게 없으면 아무것도 못 만든다.
    • 인스턴스는 무엇인가?
      • 클래스인 설계도를 바탕으로 만들어진 객체라고 보면 된다. 자동차를 예로 들면 컬러나 바퀴에 대한 생김새 등이 다를 수 있을 것이다.
  2. new 키워드와 생성자 함수

class Meal{
  //생략
}

let pizza = new Meal('pizza');

클래스를 이용해서 새로운 인스턴스를 만들고자 할 때는 반드시 new 키워드를 사용해야 한다.

만약에 생략했을 경우에는

TypeError: Class constructor Meal cannot be invoked without 'new'

이런식으로 정확히 명시해주기는 하지만 웬만하면 new 키워드를 적어주자.

  1. ES5 class vs ES6 class
  • 인스턴스 생성
 //ES5

function IronMan(color,name) {
	//인스턴스 만들어지고 난 후 실행될 코드
}

//ES6
class IronMan {
	constructor(color,name) {
		//인스턴스 만들어지고 난 후 실행될 코드
	}
}
  • 클래스 속성 정의
//ES5

function IronMan(color,name) {
	this.color = color;
	this.name = name;
}

//ES6
class IronMan {
	constructor(color,name) {
		this.color = color;
		this.name = name;
	}
}
  • 메소드 정의
//ES5

function IronMan(color,name) {
	this.color = color;
	this.name = name;
}

IronMan.prototype.fly = function(){
	//prototype 키워드를 꼭 써줘야 함
}
//ES6
class IronMan {
	constructor(color,name) {
		this.color = color;
		this.name = name;
	}
	fly() {
		
	}
}

확실히 ES5보다 편한 거 같다… ES6 최고…

여기서 this란?

위 코드에서의 this는 그냥 클래스를 통해 만들어진 인스턴스 객체다. 그렇다고 아무데나 this를 남발했다간 큰일날 수(?) 있고 솔직히 this를 공부하다 보면 한도 끝도 없긴 하지만… 한번 this를 간단하게나마 알아보자.

  1. 일반적인 경우
functionlogThis() {
  console.log(this);
}

logThis();// Window 객체

다만, use strict 키워드를 붙이게 되면 undefined 다.

  1. 메소드
var john = {
  name: 'John',
  greet: function() {
      console.log('Hi! My name is ' + this.name);
  }
};

john.greet();

일반 함수 내에서 this를 사용하게 되면 this.nameJohn을 참조하고 있으므로

당연히 결과는 Hi! My name is John이 나온다.

이거를 arrow function으로 쓰면 어떻게 될까?

var john = {
  name: 'John',
  greet: () => console.log('Hi! My name is ' + this.name),
};

john.greet();

? this.name 이 어디로 갔을까?

콘솔에는 window 객체가 나오고 vscode 같은 곳들에서는 undefined 가 나오는데

두 경우 모두 arrow function 내에서는 this 참조를 못하고 바로 상위의 스코프를 참조하고 있기 때문에 저런 현상이 나오는 것이다.

객체 지향 프로그래밍(OOP)이란?

설계도인 클래스, 이를 바탕으로 만들어진 인스턴스 객체를 Object로 해서 이러한 프로그래밍의 모든 것들을 하나의 객체로 간주하고 객체 간의 상호작용을 중심으로 생각하고 설계하는 프로그래밍 패러다임을 말한다.

객체지향 프로그래밍의 4가지 요소

  1. 캡슐화

    내부 구조와 외부 구조를 독립적으로 생각하는 것을 말한다. 예를 들어 커피머신을 예로 들면 사용자는 단순히 버튼이나 다른 조작을 하지만 실제로 외부 구조에서는 복잡하게 돌아간다. 그리고 사용자가 그러한 구조를 몰라도 커피머신을 사용할 수 있기 때문에 서로 독립적이라고 볼 수 있다.

  2. 상속

    class Animal {
      constructor(name) {
        this.speed = 0;
        this.name = name;
      }
      run(speed) {
        this.speed = speed;
        alert(`${this.name} 은/는 속도 ${this.speed}로 달립니다.`);
      }
      stop() {
        this.speed = 0;
        alert(`${this.name} 이/가 멈췄습니다.`);
      }
    }
    
    let animal = new Animal("동물");

    객체를 여러개 만들어야 할 상황이 생길 수 있다. 그러나 위 코드처럼 클래스를 여러 개 사용하게 되면, 상당히 번거롭고 중간에 오타를 낼 확률도 적지 않다.

    따라서, 상속이라는 개념을 이용하여 클래스를 상속받으면 된다.(실제로는 확장 개념에 더 가깝다고 한다.)

    class Rabbit extends Animal {
      hide() {
        alert(`${this.name} 이/가 숨었습니다!`);
      }
    }
    
    let rabbit = new Rabbit("흰 토끼");
    
    rabbit.run(5); // 흰 토끼 은/는 속도 5로 달립니다.
    rabbit.hide(); // 흰 토끼 이/가 숨었습니다!
  3. 다형성

    여러 개의 객체가 각각 같은 메소드로 호출이 되더라도 클래스가 무엇이냐에 따라 실제 동작은 다른 성질을 다형성이라고 한다.

프로토타입이란?

  • 자바스크립트 객체는 [[Prototype]] 이라는 숨김 프로퍼티라는 것을 갖는데 이 값은 null이거나 다른 객체에 대한 참조를 갖는다. 다른 객체를 참조하는 경우 이를 프로토타입이라 한다.

proto

모든 객체는 __proto__ 키워드를 이용해 접근이 가능하다.

let animal = {
  eats: true
};
let rabbit = {
  jumps: true
};

rabbit.__proto__ = animal;

alert( rabbit.eats );
alert( rabbit.jumps );

.__proto__ 키워드를 이용하면 animal이 rabbit의 프로토타입이 된다.

prototype 프로퍼티

function Person(first, last, age, gender, interests) {

  // 속성과 메소드 정의
  this.first = first;
  this.last = last;
//...
}

console.log(Person.prototype)

함수 객체 내 프로퍼티를 확인해 본 결과

prototype이 존재한다.

// 함수 객체는 prototype 프로퍼티가 있음
function func() {}
func.hasOwnProperty('prototype') // true

// 일반 객체는 prototype 프로퍼티가 없음
const obj = {}
obj.hasOwnProperty('prototype') // false
// 화살표 함수
const arrowFunc = () => {}
arrowFunc.hasOwnProperty('prototype') // false

// ES6 축약 메서드
const es6 = {
  test() {},
}
es6.test.hasOwnProperty('prototype') // true

화살표함수와 ES6 메소드에는 prototype 속성이 없다.

클래스와 인스턴스, 그리고 프로토타입


class Human {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  sleep() {
    console.log(`${this.name}은 잠에 들었습니다`);
  }
}

let kimcoding = new Human('김코딩', 30);

// 실습해보세요
console.log(Human.prototype.constructor === Human)
Human.prototype === kimcoding.__proto__; 
Human.prototype.sleep === kimcoding.sleep;

배열도 Array 생성자 함수로 만들어진 인스턴스이다.

프로토타입 체인

[참고자료 - 모던 자바스크립트 Deep Dive]

자바스크립트 객체의 프로퍼티에 접근하려고 할 때, 프로퍼티가 존재하지 않을 경우 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색하는데 이를 프로토타입 체인이라 한다.

Object.prototype

프로토타입의 체인의 최상위에 위치하는 객체는 언제나 Object.prototype이다. 그렇기 때문에 모든 객체는 언제나 Object.prototype 을 상속받는다.

참고 자료

Javascript: Uncovering mysteries of 'this' keyword

private, protected 프로퍼티와 메서드

클래스 상속

[자바스크립트 js] 객체 지향 프로그래밍 4가지 개념 / 추상화 / 캡슐화 / 상속 / 다형성 / super / instanceof

프로토타입 상속

프로토타입: [[Prototype]], proto, prototype 프로퍼티

profile
블로그 이전했습니다. https://nextjs-blog-haseungdev.vercel.app/

0개의 댓글