Today What I Learned

Javascript를 배우고 있습니다. 매일 배운 것을 이해한만큼 정리해봅니다.


1. OOP(Object-Oriented Programming, 객체 지향 프로그램)

1. OOP란?

  • 사람이 세계를 보고 이해하는 방법을 흉내낸 방법론이라고도 불린다.
    1) 프로그래밍 세계에서의 철학을 가리킴
    2) 어떤 철학? OOP 프로그래밍에서 모든 것은 객체이고, 객체로 모든 것이 설명이 가능하다는 철학

2. OOP의 4가지 컨셉과 특징

Concept Description Benefits
Encapsulation(캡슐화) 관련된 속성(변수, method)들을 클래스 혹은 객체 안에 모아두는 것 코드의 복잡도를 낮춰준다.코드의 재사용성을 높여준다.
Inheritance(상속) 부모의 특징을 자식이 물려 받는 것 불필요한 코드를 줄여준다.(이미 있는 것을 참조해서)
Abstraction(추상화) 객체의 핵심적인(공통된) 개념/기능만 묶어서 추출하는 것 복잡도를 줄이고, 사용자에 의한 수정으로 영향을 받을 확률이 적다.
Polymorphism(다형성) 하나의 method를 각 객체에서 여러 방법으로 구현할 수 있는 것 switch/case 구문 등을 사용하지 않고도 원하는 것을 구현할 수 있다.

2. Javascript에서 Object 생성하기(ES6 이전)

  • Instantiation Patterns: ES6에서 Class 문법이 나오기 전까지 자바스크립트에서 Object 생성에는 4가지 방법이 있었다.

    1. Functional : 함수를 이용해서 찍어내는 방식

    • 생성자 함수에 모든 속성값과 메소드를 할당한다.
    • 생성자 함수로 인해 만들어진 인스턴스 격의 객체에도 모든 메소드가 할당된다.
      이 때문에 메모리를 크게 차지한다.
    var Student = function (name, score) {
       var someInstance = {};
       someInstance.name = name;
       someInstance.score = score; // 속성 할당
    
       someInstance.checkScore = function() {
           console.log(this.name + ' got ' + this.score);
       } //method도 함께 할당
    
       return someInstance;
    }
    
    var student1 = ('jason', 'A'); // 생성자 함수를 이용해 instance격 객체 생성
    console.log(student1.name); // 'jason';
    console.log(student1.score); // 'A';
    console.log(student1.checkScore); //'jason got A'

2. Functional-shared

  • 생성자 함수에 따로 메소드를 할당하지 않고, 별도의 메소드 함수를 참조하는 형태로 생성하는 방식

  • extend라는 함수를 이용해 생성자 함수에 메소드 함수를 연장하는 절차가 존재한다.

  • functional에 비해, 메소드 함수를 참고하고 있어 생성자 함수를 이용해 인스턴스격의 객체를 생성할 때 매번 메소드를 할당하지 않아 메모리가 적게 차지한다.

    var extend = function(to, from) {
      for (var key in from) {
        to[key] = from[key];
      }
    } // from 객체의 속성값을 to에 넣어주는 함수
    
    var someMethods = {};
    someMethods.checkScore = function() {
      console.log(this.name + ' got ' + this.score);
    } // method만 객체에 따로 할당
    
    var Student = function (name, score) {
      var someInstance = {};
      someInstance.name = name;
      someInstance.score = score; // 속성 할당
    
      extend(someInstance, someMethods); // mehotds 객체 속성값을 생성자 함수에 넣어줌
    //혹은 Object.assign(someInstance, someMethods)도 가능
      return someInstance;
    }
    
    var student2 = ('emma', 'B'); 
    console.log(student2.name); // 'emma';
    console.log(student2.score); // 'B';
    console.log(student2.checkScore); //'emma got B'

3. Prototypal

  • functional-shared에서 별도의 메소드 함수를 만들어 연장하는 절차가 있었다면, prototypal에서는 이 과정을 Object.create()을 이용해 구현한다.

  • 특정 객체를 프로토타입으로 하는 객체를 생성해주는 방식으로 그 후에 생성된 객체에 속성값을 부여한다.

    var someMethods = {};
    someMethods.checkScore = function() {
      console.log(this.name + ' got ' + this.score);
    } // method만 객체에 따로 할당
    
    var Student = function (name, score) {
      var someInstance = Object.create(someMethods); // someMethods를 prototype으로 가지는 객체 생성
      someInstance.name = name;
      someInstance.score = score; // 속성 할당
      return someInstance;
    }
    
    var student3 = ('victor', 'C'); 
    console.log(student3.name); // 'victor';
    console.log(student3.score); // 'C';
    console.log(student3.checkScore); //'victor got C'

4. Pseudoclassical:

  • 공통적으로 사용할 속성/메소드를 만들어두고, 이를 이용해 new 키워드로 인스턴스격의 객체를 생성하는 방식

    • Object는 보통 Pseudoclassical이나 Prototypal로 많이 구현한다.
    • ES6에서는 Class라는 문법을 이용해 명시적으로 constructor 키워드를 사용하여 생성자 함수를 구현한다.
    var Student = function(name, score) {
      this.name = name;
      this.score = score; // 속성 할당
    }
    
    Student.prototype.checkScore = function() {
    console.log(this.name + ' got ' + this.score);
    } // 생성자 함수의 prototype에 method 할당
    
    var student4 = new Student('jay', 'D');
    console.log(stduent4.name); // 'jay'
    console.log(student4.score); // 'D'
    console.log(student4.checkScore); // 'jay got D'
    console.log(student4.__proto__.checkScore); // 'undefined got undefined'
    // student4.__proto__ 는 Student의 prototype을 가리키지만
    // Student.prototype.checkScore는 원형으로 this.name과 this.score에 할당된 값이 undefined이다.

3. Javascript에서 Prototype

1. 자바스크립트는 prototype 기반의 객체 지향 언어이다.

  • 자바스크립트 외 객체 지향 언어로는 JAVA, Python, Ruby 등등이 있다.
    이러한 객체 지향 언어들은 Class라는 개념이 존재하고 상위class의 속성을 Instance로 불리는 하위 객체가 내려받을 수 있다.
  • 자바스크립트는 prototype 기반이기 때문에 다른 객체 지향 언어들과 달리 Class와 그에 따른 Insatance 개념이 존재하지 않는다.
    대신, 자바스크립트는 생성자 함수와 new 키워드를 이용해 Class와 Instance 개념을 구현할 수(흉내낼 수) 있다.
  • 참고로 자바스크립트는 ES6 버전에서 Class라는 문법을 추가하였지만, 언어 기반 자체가 바뀐 것은 아니다.

2. Class와 Object

  • Class? 프로토타입으로 객체를 만들기 위한 아이디어나 청사진

  • Object는 클래스의 인스턴스라고 본다.

  • Class는 constructor라는 것을 가지고 있는데 여기서 object를 만들어 준다.

  • OOP 절차(자바스크립트는 괄호로 구현)
    1) object를 만들 수 있는 class(격의 함수)를 정의하고
    2) 그 속성과 method(격의 객체)를 정의한다.
    3) 그런 다음 class(격의 함수)를 이용해서 instance(격의 객체)를 만들어 class(격의 함수)에서 정의했던 속성과 method(격의 객체)를 구현해 활용할 수 있다.

  • Object.create(proto) 는 prototype을 참조하는 새로운 객체를 생성할 때 사용된다.

    const Obj = function(boolean) {
        this.isObj = boolean;
    }
    
    const obj1 = new Object();
    const obj2 = Object.create(Object.prototype); // obj1과 같은 결과
    const obj3 = new Obj(true);
    // obj2에서는 Object의 prototype만 가져왔다면, obj3에서는 Obj의 생성자를 실행하여서 상속 받음
    const obj4 = Object.create(Obj.prototype);
    
    console.dir(obj1); // Object - 모든 객체의 조상
    console.dir(obj2); // Object - 모든 객체의 조상
    console.dir(obj3); // Obj - 생성자 함수
    console.dir(obj4); // Obj - 생성자 함수