자바스크립트에서는 객체리터럴을 이용하거나 생성자를 이용해서 만들 수 있다.
let objLiteral = {};
let objConstructor = new Object();
리터럴은 Object 타입의 객체를 만들어내는 일종의 숏컷이고 두 번째 라인의 생성자를 이용한 코드 역시 Object 생성자이기 때문에 사실 위의 예제는 리터럴이나 생성자나 모두 객체의 내용이나 프로토타입의 구조 면에서 동일한 객체를 만들어낸다. 하지만 최상위 타입의 객체가 생성되기 때문에 이방법으로는 객체를 상속받았다고 표현하기 힘들다.
프로토타입을 이용하면 객체와 객체를 연결하고 부모 자식과 같은 관계로 상속받는 형태로 만들 수가 있다.
let objpro1 = {
who: "부모"
}
let objpro2 = {
who2: "자식"
}
objpro2.__proto__ = objpro1;
objpro2.who // "부모"
모든 객체는 하나 이상의 또다른 객체로부터 상속받는다.
상속되는 정보를 제공하는 객체를 칭한다.
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일까?
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...
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)를 한번에 정의한다.