Prototype Chain

황순은·2021년 4월 9일
0

TIL

목록 보기
6/9

객체

자바스크립트에서는 객체리터럴을 이용하거나 생성자를 이용해서 만들 수 있다.

let objLiteral = {};
let objConstructor = new Object(); 

리터럴은 Object 타입의 객체를 만들어내는 일종의 숏컷이고 두 번째 라인의 생성자를 이용한 코드 역시 Object 생성자이기 때문에 사실 위의 예제는 리터럴이나 생성자나 모두 객체의 내용이나 프로토타입의 구조 면에서 동일한 객체를 만들어낸다. 하지만 최상위 타입의 객체가 생성되기 때문에 이방법으로는 객체를 상속받았다고 표현하기 힘들다.

프로토타입

프로토타입을 이용하면 객체와 객체를 연결하고 부모 자식과 같은 관계로 상속받는 형태로 만들 수가 있다.

let objpro1 = {
  who: "부모"
}
let objpro2 = {
  who2: "자식"
}

objpro2.__proto__ = objpro1;
objpro2.who // "부모"

모든 객체는 하나 이상의 또다른 객체로부터 상속받는다.
상속되는 정보를 제공하는 객체를 칭한다.

proto, constructor, prototype의 관계

prototype : 모든 function에는 prototype 이라는 속성이 있다.

constructor : 생성자. 특정 객체가 생성될때 실행되는 코드.

__proto__ : [[Prototype]] , 프로토타입 체인이라고 불린다.

function Human(name) {
  this.name = name;
}
Human.prototype.sleep = function() {
 console.log("zzz");
}

let steve = new Human('steve');

steve.__proto__ === Human.prototype // true

Human은 최상위 Object의 프로토타입을 상속받고 steve는 그것을 다시 상속받았다. 반대로 생각했을때 steve에게 상속해준사람은 Human일까 Object일까?

ES5 & ES6

ES5 pseudoclassical Subclassing

let Human = function(name) {
  this.name = name;
}

Human.prototype.sleep = function() {
  console.log(this.name + ' is sleeping...');
}
let steve = new Human('steve');

let Student = function(name) {
  Human.call(this, name); // Human.apply(this, arguments)
}

인스턴스를 만들 원형 객체를 만들어 속성을 키:밸류 값으로 넣는다. 이 때 상위 객체로부터 상속 받을 속성이 있다면 자체 속성 정의 전, 상위 객체.call(this)의 형태(변수가 여럿이면 상위 객체.apply(this, arguments)도 가능)로 속성을 불러와 1)상속하여 그대로 사용하거나 2)하위 객체에서 새로운 속성 값으로 할당할 수 있다.

Student.prototype = Object.create(Human.prototype);
Student.prototype.constructor = Student;
Student.prototype.learn = function() {
  console.log(this.name + ' is learning...')
}

let dubu = new Student('dubu');

dubu.learn(); // dubu is learning...
dubu.sleep(); // dubu is sleeping...
steve.learn(); // Uncaught TypeError: steve.learn is not a function
steve.sleep(); // steve is sleeping...
  • Object.create(Human.prototype) 의 형태로 상위 객체인 Human을 Student 객체에 상속시켜줬다.
  • Student.proto 는 Human.prototype을 바라보고 있으므로 Student.prototype.constructor = Student(자기자신)을 선언하여 다형성을 가능하게 만들어 준다.
  • learn()은 Student객체의 독립적인 메소드로 사용될 수 있으며 상위객체인 Human에게는 영향이 없는것을 볼 수 있다.

ES6 Class Subclassing

class Human {
  constructor(name) {
    this.name = name;
  }
  sleep() {
    console.log(this.name + ' is sleeping...');
  }
}

let steve = new Human('steve');

class Student extends Human {
  constructor(name) {   // 생성자가 같을시 생략 가능(추가, 변경시는 필요)
    super(name)
    this.name = name;
  }
  learn() {
    console.log(this.name + ' is learning...');
  }
}

let dubu = new Student('dubu');

dubu.learn(); // dubu is learning...
dubu.sleep(); // dubu is sleeping...
steve.learn(); // Uncaught TypeError: steve.learn is not a function
steve.sleep(); // steve is sleeping...

class 직후 클래스 이름을 선언한 후 스코프 안에 1) constructor 영역 2) method 영역을 담는다. 만약 상위 객체를 상속 받는 하위 객체를 생성하는 과정에서는 class 하위객체이름 extends 상위객체이름 형태로 선언한다. 이전 방법과 달리 class 문법에서는 한 스코프 안에 1)과 2)를 한번에 정의한다.

  • 생성자가 동일해도 되는 경우는 상속받을 객체에서 constructor는 생략가능하다.
  • 생성자를 변경, 추가하기위해서는 constructor와 기존 생성자를 받아올 super(변수명)을 선언하고 this.변수명으로 할당이 가능하다.
profile
안녕하세요.

0개의 댓글