
📍
자바스크립트는 프로토타입 기반의 객체지향 프로그래밍 언어다.
그러니까 자바스크립트를 이루고 있는 거의
모든것이 객체다.
처음에 말했듯 자바스크립트는 프로토타입 기반의 객체지향 프로그래밍 언어다.
원시 값을 제외하고 나머지 값은 모두 객체다.
객체 지향 프로그래밍은 객체의 상태를 나타내는 데이터(프로퍼티)와 상태 데이터를 조작할 수 있는 동작(메서드)을 하나의 논리적인 단위로 묶은 복합적인 자료구조이다.
1. 상속과 프로토타입
- 프로토타입이란 객체의 원형을 뜻한다. 즉, 모든 객체는 프로토타입이라는 객체를 가지고 각각의 프로토타입으로 부터 프로퍼티와 메서드를 상속받는다.
- 상속은 객체지향 프로그래밍의 핵심 개념으로 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다.
- 자바스크립트는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다.
- 중복을 제거하는 방법은 기존의 코드를 적극적으로 재 사용하는 것이다. 코드 재 사용은 개발비용을 현저히 줄일 수 있는 방법 중 하나이다.
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());
console.log(circle2.getArea());
위 예제는 생성자 함수이다.
생성자 함수는 동일한 프로퍼티, 메서드 구조를 갖는 객체를 여러 개 생성할 때 유용하다.
하지만 이때, radius 프로퍼티 값의 경우 인스턴스 마다 다른 값을 가지지만 getArea 메서드의 경우 모든 인스턴스가
동일한 내용의 메서드를 사용한다. 즉, Circle 생성자 함수는 인스턴스를 생성할 때마다 getArea 메서드를 중복 생성하고 모든 인스턴스가 중복 소유하고 있다는 것이다.
이처럼 동일한 생성자 함수에 의해 생성된 모든 인스턴스가 동일한 메서드를 중복 소유하는 것은 메모리를 불필요하게 낭비한다. 또한 인스턴스를 생성할 때마다 메서드를 생성하므로 퍼포먼스에도 악영향을 준다.
이럴때는 어떻게 해야할까?
→ 상속을 통해 불필요한 중복을 제거 할 수 있다.
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);
// 모든 인스턴스가 부모 객체 역할을 하는 Circle.prototype 로 부터
// getArea를 상속 받는다.
console.log(circle1.getArea === circle2.getArea); // true
console.log(circle1.getArea());
console.log(circle2.getArea());
- 자신의 상태를 나타내는 프로퍼티만 개별적으로 갖고 내용이 같은 메서드는 상속을 통해 공유하여 활용한다.
2. 프로토타입 객체
- 프로토타입 객체 줄여서 프로토타입이란 객체 간 상속을 구현하기 위해 사용된다.
- 프로토타입은 어떤 객체의 상위(부모) 객체 역할을 하는 객체로서 다른 객체에 공유 프로퍼티(메서드)를 제공한다. 하위 객체는 상위 객체의 프로퍼티를 자유롭게 사용할 수 있다.
- 모든 객체는 [[Prototype]] 이라는 내부 슬롯을 가진다.
- 모든 프로토타입은 생성자 함수와 연결되어 있다.
- __proto__ 접근자 프로퍼티를 통해 자신의 [[Prototype]]에 간접적으로 접근할 수 있다.
💡 __proto__ 와 같은 접근자 프로퍼티를 사용하여 프로토타입에 접근하는 이유는 뭘까?
상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서 이다. 프로토타입은 프로퍼티 검색 방향이 한쪽 방향으로만 흘러 가야한다. 프로토타입 체인 종점이 존재하지 않으면 프로퍼티를 검색할 때 무한루프에 빠지기 때문에 아무런 체크없이 무조건적으로 프로토타입을 교체할 수 없도록 __proto__ 접근자 프로퍼티를 통해 접근하고 교체하도록 한다.
2.1 함수 객체의 prototype 프로퍼티
- 함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.
- 생성자 함수로 호출할 수 없는 non-constructor(ES6 메서드 축약 표현, 화살표 함수)는 prototype 프로퍼티를 소유하지 않고 프로토타입을 생성하지 않는다.
2.2 리터럴 표기법과 프로토타입
- 리터럴 표기법에 의해 생성된 객체도 상속을 위해 프로토타입이 필요하다. 따라서 가상적인 생성자 함수를 갖는다. 프로토 타입은 생성자 함수와 더불어 생성되며 prototype, constructor 프로퍼티에 의해 연결되어 있기 때문이다.
- 즉, 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 같이 존재한다.
✔️ 리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입
리터럴 표기법 | 생성자 함수 | 프로토타입 |
객체 리터럴 | Object | Object.prototype |
함수 리터럴 | Function | Function.prototype |
배열 리터럴 | Array | Array.prototype |
정규 표현식 리터럴 | RegExp | RegExp.prototype |
3. 프로토타입 체인
- 자바스크립트는 객체의 프로퍼티, 메서드에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티가 없다면 [[prototype]] 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다. 이를 프로토타입 체인이라고 한다.
- 프로토타입 체인은 자바스크립트가 객체지향 프로그래밍의 상속을 구현하는 메커니즘이다.
- 프로토타입 체인의 최상위에 위치하는 객체는 언제나 Object.prototype이다.
- 따라서 모든 객체는 Object.prototype의 상속을 받는다.
- Object.prototype을 프로토타입 체인의 종점이라고 한다.
- Object.prototype의 프로토타입 [[prototype]] 내부 슬롯의 값은 null이다.
- 프로토타입 체인은 상속과 프로퍼티 검색을 위한 메커니즘이다.
- 프로퍼티가 아닌 식별자는 스코프체인에서 검색한다.
스코스체인
스코프가 계층적으로 연결된 것을 말하며, 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다.
💡 스코프 체인과 프로토타입 체인은 서로 연관없이 별도로 동작하는 것이 아니라 서로 협력하여 식별자와 프로퍼티를 검색하는 데 사용된다.
4. 직접 상속
- 명시적으로 프로토타입을 지정하여 새로운 객체를 생성하는 메서드를 Object.create라고 한다.
- Object.create 메서드는 첫 번째 매개변수에 생성할 객체의 프로토타입으로 지정할 객체를 전달한다.
- 두 번째 매개변수에는 생성할 객체의 프로퍼티 키와 프로퍼티 디스크립터 객체로 이뤄진 객체를 전달한다.
- Object.create 메서드는 객체를 생성하면서 직접적으로 상속을 구현한다. 그래서 이 메서드는 몇가지 특징을 갖는다.
- new 연산자 없이도 객체를 생성할 수 있다.
- 프로토타입을 지정하면서 객체를 생성할 수 있다.
- 객체 리터럴에 의해 생성된 객체도 상속받을 수 있다.
📌 출처
모던 자바스크립트 Deep Dive(이웅모 저)

📍
자바스크립트는 프로토타입 기반의 객체지향 프로그래밍 언어다.
그러니까 자바스크립트를 이루고 있는 거의
모든것이 객체다.
처음에 말했듯 자바스크립트는 프로토타입 기반의 객체지향 프로그래밍 언어다.
원시 값을 제외하고 나머지 값은 모두 객체다.
객체 지향 프로그래밍은 객체의 상태를 나타내는 데이터(프로퍼티)와 상태 데이터를 조작할 수 있는 동작(메서드)을 하나의 논리적인 단위로 묶은 복합적인 자료구조이다.
1. 상속과 프로토타입
- 프로토타입이란 객체의 원형을 뜻한다. 즉, 모든 객체는 프로토타입이라는 객체를 가지고 각각의 프로토타입으로 부터 프로퍼티와 메서드를 상속받는다.
- 상속은 객체지향 프로그래밍의 핵심 개념으로 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 말한다.
- 자바스크립트는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다.
- 중복을 제거하는 방법은 기존의 코드를 적극적으로 재 사용하는 것이다. 코드 재 사용은 개발비용을 현저히 줄일 수 있는 방법 중 하나이다.
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());
console.log(circle2.getArea());
위 예제는 생성자 함수이다.
생성자 함수는 동일한 프로퍼티, 메서드 구조를 갖는 객체를 여러 개 생성할 때 유용하다.
하지만 이때, radius 프로퍼티 값의 경우 인스턴스 마다 다른 값을 가지지만 getArea 메서드의 경우 모든 인스턴스가
동일한 내용의 메서드를 사용한다. 즉, Circle 생성자 함수는 인스턴스를 생성할 때마다 getArea 메서드를 중복 생성하고 모든 인스턴스가 중복 소유하고 있다는 것이다.
이처럼 동일한 생성자 함수에 의해 생성된 모든 인스턴스가 동일한 메서드를 중복 소유하는 것은 메모리를 불필요하게 낭비한다. 또한 인스턴스를 생성할 때마다 메서드를 생성하므로 퍼포먼스에도 악영향을 준다.
이럴때는 어떻게 해야할까?
→ 상속을 통해 불필요한 중복을 제거 할 수 있다.
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);
// 모든 인스턴스가 부모 객체 역할을 하는 Circle.prototype 로 부터
// getArea를 상속 받는다.
console.log(circle1.getArea === circle2.getArea); // true
console.log(circle1.getArea());
console.log(circle2.getArea());
- 자신의 상태를 나타내는 프로퍼티만 개별적으로 갖고 내용이 같은 메서드는 상속을 통해 공유하여 활용한다.
2. 프로토타입 객체
- 프로토타입 객체 줄여서 프로토타입이란 객체 간 상속을 구현하기 위해 사용된다.
- 프로토타입은 어떤 객체의 상위(부모) 객체 역할을 하는 객체로서 다른 객체에 공유 프로퍼티(메서드)를 제공한다. 하위 객체는 상위 객체의 프로퍼티를 자유롭게 사용할 수 있다.
- 모든 객체는 [[Prototype]] 이라는 내부 슬롯을 가진다.
- 모든 프로토타입은 생성자 함수와 연결되어 있다.
- __proto__ 접근자 프로퍼티를 통해 자신의 [[Prototype]]에 간접적으로 접근할 수 있다.
💡 __proto__ 와 같은 접근자 프로퍼티를 사용하여 프로토타입에 접근하는 이유는 뭘까?
상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서 이다. 프로토타입은 프로퍼티 검색 방향이 한쪽 방향으로만 흘러 가야한다. 프로토타입 체인 종점이 존재하지 않으면 프로퍼티를 검색할 때 무한루프에 빠지기 때문에 아무런 체크없이 무조건적으로 프로토타입을 교체할 수 없도록 __proto__ 접근자 프로퍼티를 통해 접근하고 교체하도록 한다.
2.1 함수 객체의 prototype 프로퍼티
- 함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.
- 생성자 함수로 호출할 수 없는 non-constructor(ES6 메서드 축약 표현, 화살표 함수)는 prototype 프로퍼티를 소유하지 않고 프로토타입을 생성하지 않는다.
2.2 리터럴 표기법과 프로토타입
- 리터럴 표기법에 의해 생성된 객체도 상속을 위해 프로토타입이 필요하다. 따라서 가상적인 생성자 함수를 갖는다. 프로토 타입은 생성자 함수와 더불어 생성되며 prototype, constructor 프로퍼티에 의해 연결되어 있기 때문이다.
- 즉, 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 같이 존재한다.
✔️ 리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입
리터럴 표기법 | 생성자 함수 | 프로토타입 |
객체 리터럴 | Object | Object.prototype |
함수 리터럴 | Function | Function.prototype |
배열 리터럴 | Array | Array.prototype |
정규 표현식 리터럴 | RegExp | RegExp.prototype |
3. 프로토타입 체인
- 자바스크립트는 객체의 프로퍼티, 메서드에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티가 없다면 [[prototype]] 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다. 이를 프로토타입 체인이라고 한다.
- 프로토타입 체인은 자바스크립트가 객체지향 프로그래밍의 상속을 구현하는 메커니즘이다.
- 프로토타입 체인의 최상위에 위치하는 객체는 언제나 Object.prototype이다.
- 따라서 모든 객체는 Object.prototype의 상속을 받는다.
- Object.prototype을 프로토타입 체인의 종점이라고 한다.
- Object.prototype의 프로토타입 [[prototype]] 내부 슬롯의 값은 null이다.
- 프로토타입 체인은 상속과 프로퍼티 검색을 위한 메커니즘이다.
- 프로퍼티가 아닌 식별자는 스코프체인에서 검색한다.
스코스체인
스코프가 계층적으로 연결된 것을 말하며, 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색한다.
💡 스코프 체인과 프로토타입 체인은 서로 연관없이 별도로 동작하는 것이 아니라 서로 협력하여 식별자와 프로퍼티를 검색하는 데 사용된다.
4. 직접 상속
- 명시적으로 프로토타입을 지정하여 새로운 객체를 생성하는 메서드를 Object.create라고 한다.
- Object.create 메서드는 첫 번째 매개변수에 생성할 객체의 프로토타입으로 지정할 객체를 전달한다.
- 두 번째 매개변수에는 생성할 객체의 프로퍼티 키와 프로퍼티 디스크립터 객체로 이뤄진 객체를 전달한다.
- Object.create 메서드는 객체를 생성하면서 직접적으로 상속을 구현한다. 그래서 이 메서드는 몇가지 특징을 갖는다.
- new 연산자 없이도 객체를 생성할 수 있다.
- 프로토타입을 지정하면서 객체를 생성할 수 있다.
- 객체 리터럴에 의해 생성된 객체도 상속받을 수 있다.
📌 출처
모던 자바스크립트 Deep Dive(이웅모 저)