생성자 함수 와 Class (01)

목차 📕

1. 생성자 함수란와 Class에 대하여 다음과 같은 목차로 다뤄보려 합니다.

하지만 막상 다뤄보니 다 다루진 못했어요 못 다룬 내용에 대해서는 다음 편에 다뤄보도록 할게요 (상속패턴, ES6 Class)

  • 1.1 생성자 함수 동작 및 설명
  • 1.2 예제로 살펴보기
  • 1.3 상속
  • 상속의 종류도 (다음편에...)

2. 생성자 함수 쓸 때 Tips

  • 2.1 대문자로 시작하는 Convnetion
  • 2.2 메소드는 Constructor.Prototype에

3. ES6 Class and Objcet.create(다음편에 ...)

1.생성자 함수 동작 및 설명

생성자 함수는 무엇일까? new로 무엇을 생성한다는 것일까요? 답은 바로 Plain 객체를 생성합니다 아래 영상에서 나온 설명을 참고해서 정리해보면

  1. 새로운 객체를 생성한다. {}
  2. 이 객체에 prototype을 constructor.prototype과 연결한다.
    Object.setPrototype(obj, constructor.prototype)
  3. constructor.apply(obj, ..arguments) this context객체를 obj로 정의해줍니다. 그러면 생성자 함수에서 this로 정의해놓은 부분이 자연스레 새로 생성된 obj 객체가 되서 이 객체에 속성들이 붙겠죠
  4. 마지막 이 obj를 return 해줍니다 😄 단 fn에서 return값을 정의해주면 그 return값을 내어줍니다.

고로 일반 function과 생성자 함수로 쓸 때 구분을 지어주어야 겠죠 일반적인 convention으로 대문자로 시작해줍시다.

1.2 예제로 살펴보는 생성자 함수

function Person(name){
  console.log(this) // context객체
  this.name = name;
  this.say = function(saying){
    console.log(`I am ${saying}`)
  }
  this.think = function(what){
    console.log(`I am thinking ${what}`)
  }
}

var dali = new Person('dali')

브라우저에서
dali->
dali를 찍어서 열어보면 생성자 함수 표시가 나오고

스크린샷 2019-06-30 오후 7 12 38

정의해놓은 속성들을 가지고 있는 객체라고 나온다 또 호기심이 많은 사람들은 눌러보면
__proto__ 프로토타입 링크를 통해서 -> constructor 프로퍼티가 생성자 함수랑 연결되어 있다는 것을 알 수 있다.
__proto__: constructor: ƒ Person(name) 또 생성자 함수도 Person.prototype 프로퍼티 역시 constructor: ƒ Person(name) 가지고 있는데 Person.prototype === dali.__proto__ //true 가 나오면서 같은 곳을 가르키고 있음을 알 수 있다

1.3 상속

여담이지만 잘 쓰기 어려운 패턴이, 상속이라고 한다. 많은 분들이 상속을 잘 못 써서, 설계가 잘 못되는 경우가 빈번하다고 ...상속을 잘 쓰려면 많은 훈련이 필요하다는 사실 인지하고 들어가보자

-MDN_Inheritance

상속이라기보다 Class에 extends라는 말에 맞게 의미상으로 확장에 더 걸맞는다고 한다. 하지만 관습적으로 상속이라는 용어로 이미 통용이 많이 되고 있으니 상속이라고 얘기를 하겠다.

객체에 내부속성 prototype이 연결 되어 상위 확장을 지어준 객체를 가르키고 또 이 객체는 [[prototype]] 으로 상속되기 전 객체를 가르키고 이런식으로 프로토타입 체이닝을 통해서 쭈욱 올라갈 수 있을 때 결국 최정목적지는 Object를 가르키게 된다. Object__proto는 null

1.3 상속

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

Person.prototype.think = function() {
  return `${this.name} is thinking`;
};

function Developer(name, skill) {
  // super() 처럼 Person.call을 이용해서 확장 기반으로 할 constructor를 실행시켜준다.
  Person.call(this, name);
  this.skill = skill;
}
// 핵심 prototype을 prototype 링크 연결된 객체를 통해서 연결시킨다 (feat. Object.create)
Developer.prototype = Object.create(Person.prototype);
//
// instance of 로 검출할 때 Constructor.prototype으로 연결 관계를 체크하기 때문에
// 프로토타입 링크로 연결되어 있기 때문에 상속(확장)관계를 체크할 수 있다.
// 다만 이제  developer랑 연결된 consturcotr 속성이 없어서 인스턴스에서 직접 접근은 할 수 없어진다.
//
ES6;
Object.setPrototypeOf(Devleoper.prototype, Person.prototype);

// Devleoper.prototype -> Person.prototype 객체를 가르키는지 확인

Devleoper.prototype.coding = function() {
  return `${this.name} is ${this.skill} coding `;
};

var dali = new Devleoper("dali", "js");

dali.think(); //
dali.coding(); //

예제로 상속 구현에 대해서 알아보았다. Prototype 링크들끼리 연결시켜주기만 하면 된다. 분명 몇 번 봤는 것 같은데도 ... 매번 잘 까먹는 것을 보면 직접 구현해보면서 연습해보지 않는 이상 'ㅁ';;; 다음에는 상속을 좀 이용해서 뭐라도 만들어봐야 겠네요

1.3.2 메소드 상속

var o = {
  a: 2,
  m: function(b) {
    return this.a + 1;
  }
};
var p = Object.create(o);
// 새객체를 만들면서 [[prototype]]을 o와 연결시킨다.
p > {};
__proto__: a: 2;
m: ƒ(b);

1.3.3 프로토타입 상속의 종류

MDN에서 소개해주는 3가지 종류의 상속

  • 위임형 상속 위임형 상속은 앞서 살펴본 new나 es6 class 기반 인스턴스를 만드는 상속인데

장점 메모리 절약 메소드로 한 Constructor 함수들을 공유해서 쓴다.

단점

  1. Constructor(Functioin).prototype과 쓸데없는 binding되기 된다.
  2. 반대로 프로토타입에 변경이 모든 곳에 공유된다. 상태변경 전파를 막기 위해서 각 객체마다 상태 값의 복사값을 만들어야 한다.
  • 연결형 상속

연결형 상속은 한 객체의 속성을 다른 객체에 모두 복사함으로써 상속을 구현하는 방법이다.

필요한 부분만 유연하게 합성해서 넣어주기 좋을 것 같다 😄 ... 이 부분도 좀 써보고 더

-- Factory 함수로 만들어 사용하는 방식이다.

-medium-참고글

다뤄보려 하기에 양도 많고, 공부도 덜 된 것 같아서 2부에 상속과 class도 같이 다뤄보도록 하겠다 😄

생성자 함수 쓸 때 Tips

2.1 생성자 함수는 대문자로

일반 fn과 구분되도록 return값 정의하지 않고 😄

2.2 메소든느 프로토타입에다가 Prototype

일반적으로 생성자함수 객체에 prototype이 가르키는 곳에 함수를 다 공유해서 쓰면 객체마다 methods를 따로 가지지 않아도 이 공간으로 (dali.__proto__ === Person.prototype) 공유해서 쓸 수가 있겠지요 😄

function Person(name) {
  console.log(this); // context객체
  this.name = name;
}

Person.prototype.say = function(saying) {
  console.log(`I am ${saying}`);
};
Person.prototype.think = function(what) {
  console.log(`I am thinking ${what}`);
};

2.3 생성자 함수 prototype을 뒤에서 수정하는 일

정의 한 곳 말고 또 다시 prototype을 직접 수정하게 되면 이로 상속 관계를 체크해서 연결되어 있는 부분 역시 영향을 끼치게 됨으로서 사이드 이펙트를 초래한다.

ETC

저는 JS만 해서 잘 모르겠지만... 어서 다른 언어들도 다뤄봐야 겠네요 (많이 다르다고 하지만,) 기본적으로 인스턴스냐 객체냐 미리 정의한 속성을 가진 것을 찍어내기 위해 만드는 것은 비슷할 것 같아요 비유로 설명할 때 많이 들어보셨을 것 같은 붕어빵, 게임 캐릭터, 자동차 공장 ...

전통적인 OOP 기반 언어들과 다르게 JS에서는 Prototype 기반 언어로 상속을 구현하고 있습니다.

Reference

Class

  • 다음편에 따로 다뤄보겠습니다.