IM Sprint #1 - OOP / Object / Prototype

윤슬기·2019년 11월 14일
0

for IM Sprint

목록 보기
1/8

IM Sprint

IM Sprint 시리즈는, 코드 스테이츠의 웹 개발 심화 코스인 Immersive 코스에서 수강생들과 함께 이야기 나눌 주제에 대해 빠르게 학습하고 정리한 글이다.


OOP란 무엇인가

프로그래밍 언어에는 절차 지향적 언어와 객체 지향적 언어가 있다. 자바스크립트는 객체 지향적 언어인데, 객체 지향이란 무엇일까?
객체 지향 프로그래밍이란 프로그래밍 디자인 철학 중 하나로, 모든 요소를 'Object'로 다루는 방법이다. 이는 사람이 세계를 바라보고 이해하는 방법을 흉내낸 방법론이다.
Object란, 어떤 사물 혹은 개념 그 자체이다. 객체 지향 프로그래밍은 Object가 가진 속성들 - 크기, 색상, 이름이나 동적인 '달린다'라는 움직임등 - 을 토대로 큰 틀을 만들어 그 틀을 이용해 그와 비슷한 다른 Object들을 생성할 수 있도록 설계한다.
여기서 그 틀은 class, 그를 토대로 만들어진 object를 인스턴스라 말한다. 인스턴스를 만들 때엔 class를 기반으로 요소들을 추가, 변경, 삭제하여 필요한 모양을 만든다.

OOP에는 네 가지 컨셉이 있다.

  1. 캡슐화 encapsulation : Object에 해당되는 속성들을 내부에 모아 놓는다.
  2. 상속 inheritance : class를 기반으로 생성한 인스턴스는 class의 속성을 그대로 가지고 있다.
  3. 추상화 abstraction : 내부에서는 복잡한 구조를 띄더라도, 바깥에서 그를 이용할 때는 손쉽게 이용할 수 있다.
  4. 다형성 polymorphism : class에 속한 메서드를 여러 인스턴스에서 사용할 때, 같은 메서드이지만 인스턴스에서는 각각 다른 방식으로 사용된다.

JS ES5 에서 class를 생성하는 네 가지 방법

1. Functional

var Car = function(position) {
  var someInstance = {};
  someInstance.position = position;
  someInstance.move = function() {
    this.position = this.position + 1;
  }
  return someInstance;
}

var car1 = Car(5);
car1.move();
car1.move();
car1.move();
// move()함수를 3번 실행

console.log(car1);
// { position: 8, move: [Function] }

2. Functional Shared

아래 코드는 extend 함수를 통해 someMethods에 있는 메서드에 접근하도록 1번의 코드를 변형하였다. 이렇게 구성하면 Car의 인스턴스를 만들었을 때, 인스턴스들이 someMethods에 담긴 함수를 참조하므로 someInstace에 모든 속성을 넣어 인스턴스를 만든 경우보다 메모리를 적게 차지한다.

var extend = function(to, from) {
  for (var key in from) {
    to[key] = from[key];
  }
};

var someMethods = {};
someMethods.move = function() {
  this.position = this.position + 1;
};
someMethods.run = function() {
  this.position = this.position + 10;
}

var Car = function(position) {
  var someInstance = {
    position: position
  };
  extend(someInstance, someMethods);
  return someInstance;
}

var car1 = Car(5);
car1.move();
car1.move();
car1.run();

console.log(car1);
// { position: 17, move: [Function], run: [Function] }

3. Prototypal

Object.create() 를 이용하는 방법. 여기서는 someMethods 객체를 프로토타입으로 삼는 객체를 생성했다.

var someMethods = {};
someMethods.move = function() {
  this.position = this.position + 1;
};
someMethods.run = function() {
  this.position = this.position + 10;
}

var Car = function(position) {
  var someInstance = Object.create(someMethods);
  someInstance.position = position;
  return someInstance;
}

var car1 = Car(5);

car1.move();
console.log(car1);
// { position: 6 }

4. Pseudoclassical

가장 많이 사용되는 방법. prototype 에 공통적으로 사용할 함수나 속성들을 지정하여 모든 인스턴스에서 사용한다. 이 때는 new 키워드로 인스턴스를 생성한다.

var Car = function(position) {
  this.position = position;
};

Car.prototype.move = function() {
  this.position = this.position + 1;
}

var car1 = new Car(5);
car1.move();

console.log(car1);
// Car { position: 6 }

Prototype

자바스크립트는 class가 아닌 prototype을 기반으로 상속과 비슷한 효과를 구현한다.
생성자 함수(위에서 class로 칭한 '틀'역할)가 언어 구조적으로 가지고 있는 'prototype'에 속한 속성들은, 생성자 함수를 통해 만들어진 모든 인스턴스들이 접근할 수 있다.
그리고 자바스크립트의 모든 객체들은 'Object' object이기 때문에, 'Object' object 가진 prototype의 속성들을 모든 객체들이 접근하여 사용할 수 있다. Object는 모든 객체들의 조상과도 같다.

예를 들어 Array()생성자를 이용해서 생성한(혹은 arr = [1, 2] 라고 적어 생성한) 배열은 Array.__proto__ 에 속한 모든 속성들에 접근할 수 있다. 그리고 Array() 생성자는 Object이므로, Object.__proto__ 의 속성 역시 가지고 있다. 그래서 배열 arr 역시 Object.__proto__에 속한 속성들에 접근 가능하다.

const arr = [1,2]
console.dir(arr);
// 콘솔에서 내용을 확인하면, arr의 __proto__가 Array(0)임을 확인할 수 있다.
// 그 탭을 열어 Array(0)의 __proto__를 확인하면, Object이다.
// 그 탭을 열면 Object.__proto__에 속한 메서드의 목록을 볼 수 있다.
// 그 중 Array.__proto__에는 없는, hasOwnProperty() 를 arr에 사용한다면?

console.log(arr.hasOwnProperty(1));
// true
profile
👩🏻‍💻

0개의 댓글