#1. 프로토타입

1. 프로토타입(Prototype)이란?

  • 객체지향언어에서는 클래스 기반 객체지향과 프로토타입 기반 객체지향으로 구분 된다.
    • 프로토타입은 예전 스타일이고, 클래스는 최신 스타일
    • 현재는 프로토타입보다 클래스가 더 많이 쓰인다. (잘 안쓰여도 개념은 알고 있어야 한다)
  • ES5 버전 까지의 자바스크립트는 프로토타입 기반 객체지향 언어에 해당된다. (ES6 부터 클래스 도입)

 

2.  객체의 의미

프로토타입과 클래스를 이해하기 위해서는 객체 라는 것을 알아야 한다.

  • 하나의 변수 안에 비슷한 특성을 갖는 변수와 함수가 내장된 형태이다.
  • 객체 안에 내장된 변수를 멤버변수 혹은 property(속성) 라고 한다.
  • 객체 안에 내장된 함수는 메서드라고 한다 (함수 == 메서드 라고 봐도 된다)

 

3. 생성자 함수

1) 생성자 함수 정의

  • 함수를 new 연산자를 사용하여 호출하는 경우, 이 함수는 자바스크립트에 의해 객체를 만들기 위한 함수로 분류된다.
    • 자바스크립트는 아무 함수에다가 new 만 붙이면 생성자 함수가 될 수 있다 (좋지않다)
    • 함수의 목적을 확실히 하기 위해 생성자 함수는 첫글자를 대문자로 표시한다.
  • 이렇게 사용되는 함수를 생성자(Constructor)라고 한다.
  • 생성자를 호출하면서 리턴 받는 변수는 생성자 함수 자체의 리턴 유/무에 상관 없이 객체가 된다.
  • 화살표함수 형식은 생성자로 사용할 수 없다.
function 함수이름() {
  실행할 코드
};

const 객체이름 = new 함수이름();

 

2) 생성자에 멤버변수 포함시키기

  • 생성자 함수안에서 this 키워드를 통해 정의한 변수는 객체의 멤버변수 역할을 한다.
  • 멤버변수는 객체 내부에 포함되는 형식으로 존재한다.
  • 같은 생성자를 통해 할당된 객체는 동일한 자료 구조를 갖지만 각각 다른 정보를 저장할 수 있다.
  • 일반적으로 멤버변수는 일반 변수와 구분하기 위해 언더바( _ ) 로 시작한다.
function Example() {

  // 멤버변수 정의하기
  // 일반적으로 멤버변수는 일반 변수와 구분하기 위해 언더바로 시작하는 이름을 갖는다.
  this._sample1 = null;
  this._sample2 = null;
};

// 생성자를 통한 객체 만들기
const a = new Example();
a._sample1 = "Hi";
a._sample2 = "Bye";
console.log(a)  // Example { _sample1: 'Hi', _sample2: 'Bye' }

const b = new Example();
b._sample1 = "Hello";
b._sample2 = "World";
console.log(b);  // Example { _sample1: 'Hello', _sample2: 'World' }

 

3) 파라미터를 갖는 생성자

  • 객체에 포함되는 멤버변수의 초기값을 설정하기 위한 용도로 생성자 함수는 파라미터를 갖을 수 있다.
  • 생성자 파라미터를 통해 객체 생성시 초기값을 한번에 설정하면, 객체를 생성한 후 개별적으로 파라미터를 지정하는 것 보다 전체 코드가 축약된다.
const Example = function(p1, p2) {
  this._p1 = p1;
  this._p2 = p2;
};

const a = new Example("Hi", "Bye");
const b = new Example("Hello", "World");

console.log(a);  // Example { _p1: 'Hi', _p2: 'Bye' }
console.log(b);  // Example { _p1: 'Hello', _p2: 'World' }

 

4. 메서드

  • 객체에 포함된 함수
  • 특정한 목적을 위한 함수가 다수 존재할 때, 이 함수들을 그룹화 해 놓은 형태를 객체로 볼 수 있다.
  • 자바스크립트의 모든 객체는 prototype 이라는 속성을 갖는다.
  • 이 속성을 생성자 함수에 활용하면 생성자 함수에 속한 다른 변수나 함수를 추가할 수 있다. (주로 함수 추가에 사용)
    • 즉, 먼저 정의된 생성자의 기능을 prototype을 통해 확장할 수 있다.
생성자함수.prototype.메서드이름 = function(파라미터1, 파리미터2) {
  실행할 코드
  return 값;
};

// 메서드 호출
const 객체이름 = new 생성자함수();
객체이름.메서드이름();

--------------------

// prototype을 활용한 메서드 정의
const Example = function(x, y) {
  this._x = x;
  this._y = y;
};

Example.prototype.getOutput = function() {
  // 객체안에 속한 메서드 안에서는 생성자가 정의한 멤버변수를 사용할 수 있다.
  console.log(`${this._x}, ${this._y} 출력`);
}

// 객체 생성
const a = new Example("아아아", "오오오");
// 객체에 속한 메서드 호출
a.getOutput();  // 아아아, 오오오 출력

// 다른 객체 생성
const b = new Example("히히히", "헤헤헤");
// 호출
b.getOutput();  // 히히히, 헤헤헤 출력

// 다른 객체에서 멤버변수를 수정할 수 있다. (원본 변경x)
b._x = "멤버변수 수정1"
b._y = "멤버변수 수정2"
b.getOutput();  // 멤버변수 수정1, 멤버변수 수정2 출력

 

5. getter, setter

객체지향에서는 객체를 통한 멤버변수의 직접 접근이 멤버변수에 값을 대입하는 과정에서 그 값의 적절성을 판단할 수 없고, 무조건적으로 대입하기 때문에 코드 보안에 부적절 할 수 있다.

  • setter : 멤버변수에 값을 간접적으로 대입하는 특수한 형태의 함수
  • getter : 멤버변수의 값을 리턴 받기 위해 사용하는 특수한 형태의 함수

1) getter, setter 정의하기

Object.defineProperty(생성자이름.prototype, "함수이름", {
  get: function() {
  	실행할 코드
    return this.멤버변수
  },
  
  set: function(파라미터) {
  	실행할 코드
    this.멤버변수 = 파라미터;
  }
});

 

2) getter, setter 활용하기

  • 함수지만 변수처럼 사용한다.
const 객체 = new 생성자이름();

// setter를 호출, 대입되는 값은 setter에 전달되는 파라미터다.
객체.함수이름 = OOO;

// getter를 호출, 멤버변수를 대입하는 것 같지만, 실제로는 getter를 호출해서 리턴값을 받는다
const 변수 = 객체.함수이름;

---------------------

function Example() {
  this._x = null;
};

Object.defineProperty(Example.prototype, "value", {
  get: function() {
    console.log("value에 대한 getter 호출");
    // 멤버변수의 값을 반환하는 기능
    // 반환 전에 필요하다면 멤버변수의 값을 가공하여 반환할 수도 있다.
    return this._x;
  },

  set: function(pm) {
    console.log("value에 대한 setter 호출");
    // 파라미터의 값을 멤버변수에 복사하는 기능
    // 필요하다면 파라미터 값을 가공하여 멤버변수에 복사 할 수 있다.
    this._x = pm;
  }
});

// 객체 생성
const y = new Example();
y.value = "와이";  // value에 대한 setter 호출

const z = y.value;  // value에 대한 getter 호출

 

6. JSON 구문 형식 활용

  • 생성자이름.prototype = { } 형식으로  getter, setter, 메서드 등을 한번에 추가할 수 있다.
  • 이러한 형식으로 생성자, 멤버변수, getter, setter, 메서드 등이 묶여 있는 단위를 클래스라고 한다.
  • 클래스에 정의된 기능을 하나의 변수에 모두 부여한 형태가 객체이다.

1) 클래스 완전체 정의

  • 생성자는 익명함수 형식으로 정의할 수 도 있다.
function 생성자이름(파라미터1, 파라미터2) {
  this.멤버변수1 = 파라미터1;
  this.멤버변수2 = 파라미터2;
};

 

2) JSON을 활용하여 getter, setter와 메서드 추가하기

  • 객체 사이사이에 콤마( , )를 넣어줘야 에러가 안난다.
생성자이름.prototype = {

  // getter와 setter의 이름은 동일해야 하고, 멤버변수 수 만큼 정의된다.
  get getter이름() {
  	return this.멤버변수;
  },
  
  set setter이름(파라미터) {
  	this.멤버변수 = 파라미터;
  },
  
  메서드1이름 : function() {
    실행할 코드
  },

  메서드2이름 : function() {
	실행할 코드
  }
};

// 정의된 클래스를 통해 객체 생성
const 객체 = new 생성자이름();

// const 객체로 선언된 객체는 객체 참조 변수라 부르고,
// new 생성자이름() 부분에서 생성된 object를 인스턴스 라고 한다.
  • 사용 예시
// 생성자와 멤버변수 정의
function Example(x, y) {
  this._x = x;
  this._y = y;
};

// getter, setter, 메서드 일괄 정의
Example.prototype = {

  // 멤버변수 _x에 대한 getter, setter
  get x() {
    return this._x;
  },
  set x(pm) {
    this._x = pm;
  },

  // 멤버변수 _y에 대한 getter, setter
  get y() {
    return this._y;
  },
  set y(pm) {
    this._y = pm
  },

  // 메서드 생성
  ouput: function() {
    console.log(`${this.x} 과 ${this.y} 출력`);
  }
};

// 생성자를 통한 객체 생성
const a = new Example("엑스값", "와이값");

// getter를 통한 멤버변수 반환
console.log(a.x);  // 엑스값
console.log(a.y);  // 와이값

// 메서드 호출
a.ouput();  // 엑스값과 와이값 출력

// setter를 통한 멤버변수 변경
a.x = "곱창";
a.y = "육회"

// 메서드 호출
a.ouput();  // 곱창 과 육회 출력

+ Recent posts