자바스크립트의 경우 객체지향 언어이지만, Java와 같은 클래스 기반이 아닌 Prototype 기반 객체지향 언어이다.
자바스크립트의 모든 객체는 자신의 부모 객체와 연결되어 있으며, 이러한 부모 객체를 Prototype 객체또는 Prototype이라 한다.
자바스크립트의 모든 객체들은 [[prototype]]이라는 인터널 슬롯을 가지며, __proto__로 접근가능하다. 또한 [[prototype]]의 값은 부모 객체 즉 Prototype 객체를 의미한다.
[[prototype]]의 값은 객체가 생성될 때 객체 생성 방식에 따라 결정된다. 예를 들어, 객체 리터럴에 의해 생성된 객체의 프로토타입은 Object.prototype이며, 생성자 함수로 생성된 객체의 프로토타입은 생성자 함수의 prototype 프로퍼티에 바인딩되어 있는 객체이다.
const person = {
lastName: 'Lee',
age: 25
}
console.dir(person)
둘다 prototype 객체를 가리키고 있지만, [[prototype]]은 생성된 객체의 입장에서 부모의 객체를 가리키고 prototype 프로퍼티의 경우 생성자 함수로 생성될때 부모역할을 할 객체를 가리킨다.
function Person(lastName) {
this.lastName = lastName
}
const lee = new Person("Lee")
console.dir(Person)
console.dir(lee)
프로토타입 객체는 constructor 프로퍼티를 갖는다. constructor 프로퍼티는 객체의 입장에서 자신을 생성한 객체를 가리킨다.
function Person(lastName) {
this.lastName = lastName
}
const lee = new Person("Lee")
위와 같은 코드를 도식화 해보면 아래와 같다.
따라서 아래와 같은 결과가 나온다.
console.log(Person.prototype.constructor === Person) // true
console.log(lee.constructor === Person) // true
특정 객체의 프로퍼티나 메소드에 접근하려 할 때, 해당 객체에 접근하려는 프로퍼티나 메소드가 없다면 [[Prototype]]을 따라 부모 객체의 프로퍼티와 메소드를 차례대로 검색한다.
객체 리터럴 방식으로 객체를 생성할 경우, 자바스크립트는 내부적으로 Object() 생성자 함수를 사용해 객체를 생성한다.
const lee = {
lastName: "Lee",
gender: "Male",
introduce: function() {
console.log(`I'm ${this.lastName}`)
}
위와 같이 객체를 생성할 경우 아래와 같이 표현 할 수 있다.
hasOwnProperty
라는 함수가 없음에도 lee.hasOwnProperty("gender")
가 가능한 이유는 프로토타입 체이닝으로 부모 객체를 따라 가면서 hasOwnProperty
메소드를 찾기 때문이다.따라서 아래와 같은 결과가 나온다.
console.log(lee.__proto__ === Object.prototype) // true
console.log(Object.prototype.constructor === Object) // true
console.log(lee.hasOwnProperty("gender")) // true
console.log(Object.prototype.hasOwnProperty("hasOwnProperty") // true
함수를 생성자로 이용해 객체를 생성하기 위해서는 함수를 선언해야 한다. 자바스크립트에서 일반적인 함수 선언방식은 Function()을 생성자 함수로 사용해 선언하는 것과 같다.
function Person(lastName, gender) {
this.lastName = lastName
this.gender = gender
this.introduce = function() {
console.log(`I'm ${this.lastName}`)
}
}
const lee = new Person("Lee", "Male")
위와 같이 객체를 생성할 경우 아래와 같이 도식화 할 수 있다.
따라서 아래와 같은 결과가 나온다.
console.log(lee.__proto__ === Person.prototype) // true
console.log(Person.prototype.__proto__ === Object.prototype) // true
console.log(Person.prototype.constructor === Person) // true
console.log(Person.__proto__ === Function.prototype) // true
console.log(Function.prototype.__proto__ === Object.prototype) // true
console.log(Object.__proto__ === Function.prototype) // true