자바스크립트는 명령형, 함수형, 프로토타입 기반 객체지향프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어
→ 즉, 자바스크립트는 프로토타입 기반의 객체지향 프로그래밍 언어
상속 : 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 개념
function Circle(radius) {
this.radius = radius;
this.getArea = function() {
return Math.PI * this.radius ** 2;
};
}
const circle1 = new Circle(1);
const circle2 = new Circle(2);
console.log(circle1.getArea === circle2.getArea); // false
console.log(circle1.getArea()); // 3.141592...
console.log(circle2.getArea()); // 12.5663706...
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.getArea = function() {
return Math.PI * this.radius ** 2;
};
const circle1 = new Circle(1);
const circle2 = new Circle(2);
console.log(circle1.getArea === circle2.getArea); // true
console.log(circle1.getArea()); // 3.141592...
console.log(circle2.getArea()); // 12.5663706...
생성자 함수가 생성한 모든 인스턴스는 자신의 상위 객체 prototype의 모든 프로퍼티와 메서드를 상속받음
이때 메서드는 단 하나만 생성되어 Circle.prototype의 메서드로 할당되어 있음
→ 즉, 자신의 상태를 나타내는 radius 프로퍼티만 개별적으로 소유하고, 내용이 동일한 메서드는 상속을 통해 공유하여 사용
모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지며, 이 내부 슬롯의 값은 프로토타입의 참조
모든 객체는 하나의 프로토타입을 갖고, 모든 프로토타입은 생성자 함수와 연결되어 있음
→ 객체와 프로토타입과 생성자 함수는 서로 연결되어 있다.
__proto__
접근자 프로퍼티모든 객체는
__proto__
접근자 프로퍼티를 통해 자신의 프로토타입, 즉 [[Prototype]] 내부 슬롯에 간접적으로 접근할 수 있음
__proto__
는 접근자 프로퍼티
__proto__
접근자 프로퍼티를 통해 프로토타입에 접근하는 이유
__proto__
접근자 프로퍼티는 객체가 직접 소유하는 프로퍼티가 아닌 Object.prototype의 프로퍼티__proto__
접근자 프로퍼티를 코드 내에서 직접 사용하는 것을 권장하지 않음
함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킴
// 함수 객체
(function () {}).hasOwnProperty('prototype'); // true
// 일반 객체
({}).hasOwnProperty('prototype'); // false
// 화살표 함수 : non-constructor
const Person = name => {
this.name = name;
};
// non-constructor는 prototype 프로퍼티를 소유하지 않고, 프로토타입을 생성하지 않음
console.log(Person.hasOwnProperty('prototype')); // false
console.log(Person.prototype); // undefined
// ES6의 메서드 축약 표현으로 정의한 메서드 : non-constructor
const obj = {
foo() {}
};
// non-constructor는 prototype 프로퍼티를 소유하지 않고, 프로토타입을 생성하지 않음
console.log(obj.foo.hasOwnProperty('prototype')); // false
console.log(obj.foo.prototype); // undefined
구분 | 소유 | 값 | 사용 주체 | 사용목적 |
---|---|---|---|---|
__prototype__ 접근자 프로퍼티 | 모든 객체 | 프로토타입의 참조 | 모든 객체 | 객체가 자신의 프로토타입에 접근 또는 교체하기 위해 사용 |
prototype 프로퍼티 | constructor | 프로토타입의 참조 | 생성자 함수 | 생성자 함수가 자신이 생성할 객체의 프로토타입을 할당하기 위해 사용 |
모든 프로토타입은 constructor 프로퍼티를 가지고, 이 constructor 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킴
이 연결은 함수 객체가 생성될 때 이뤄짐
// 생성자 함수
function Person(name) {
this.name = name;
}
const me = new Person('Lee');
// me 객체의 생성자 함수는 Person
console.log(me.constructor === Person); // true
리터럴 표기법에 의한 객체 생성 방식과 명시적으로 new 연산자와 함께 생성자 함수를 호출하여 인스턴스를 생성하지 않는 객체 생성 방식
const obj = {};
const add = function (a, b) { return a + b; };
const arr = [1, 2, 3];
// 정규 표현식 리터럴
const regexp = /is/ig;
프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성됨
생성자 함수로서 호출할 수 있는 함수(constructor)는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성됨
빌트인 생성자 함수도 일반 함수와 마찬가지로 빌트인 생성자 함수가 생성되는 시점에 프로토타입 생성
객체 생성 방법
- 객체 리터럴
- Object 생성자 함수
- 생성자 함수
- Object.create 메서드
- 클래스 (ES6)
→ 추상연산 OrdinaryObjectCreate에 의해 생성
__proto__
에 의한 직접 상속