자바스크립트는 프로토타입 기반의 객체 지향 프로그래밍 언어이다. 여기서 객체 지향 프로그래밍이란, 코드를 객체 단위로 구조화하여 관련된 데이터와 기능을 함께 묶어서 사용하는 프로그래밍 패러다임을 의미한다.
객체 생성과 속성
객체는 속성과 메서드를 포함하며, 프로토타입은 객체의 상속을 위해 사용된다.
자바스크립트에서 객체는 중괄호({})로 감싸서 생성하며, 속성과 메서드를 포함할 수 있다. 속성은 객체 내부의 변수와 같은 역할을 하며, 메서드는 객체 내부의 함수와 같은 역할을 한다.
// 객체 생성
let person = {
name: "Isaac",
age: 23,
sayHello: function() {
console.log("Hello!");
}
};
// 객체 속성 접근
console.log(person.name); // 출력: Isaac
// 객체 메서드 호출
person.sayHello(); // 출력: Hello!
프로토타입
자바스크립트에서 모든 객체는 자신의 부모 역할을 하는 프로토타입(prototype) 객체를 가지고 있다.
객체는 프로토타입 객체의 속성과 메서드를 자신의 것처럼 사용할 수 있다. 이를 통해 상속과 객체 간의 관계를 형성할 수 있다. 이때 프로토타입은 객체 생성자 함수의 prototype 속성에 저장된다.
프로토타입은 자바스크립트에서 객체 간의 상속과 프로퍼티 공유를 가능하게 한다. 객체 생성자 함수의 prototype 속성에 프로토타입을 정의하고, 객체는 프로토타입의 속성과 메서드를 자신의 것처럼 사용할 수 있다. 또한, 프로토타입 체인을 통해 객체들 간에 상속 관계를 형성하고, 코드의 재사용성과 유지보수성을 향상시킬 수 있다.
프로토타입 체인
프로토타입은 다른 객체를 참조하는데, 객체가 어떤 속성이나 메서드를 찾을 때 자신의 프로토타입을 검색하고, 그 프로토타입의 프로토타입을 계속해서 검색하는 과정을 프로토타입 체인이라고 한다. 이를 통해 객체들 간에 상속 관계를 형성하고, 상위 객체의 속성과 메서드를 하위 객체가 상속받을 수 있다.
프로토타입 사용 방법
// Person 객체 생성자 함수 정의
function Person(name) {
this.name = name;
}
// Person 프로토타입에 sayHello 메서드 추가
Person.prototype.sayHello = function() {
console.log("Hello, my name is " + this.name);
};
// Person 객체 생성
let person = new Person("Isaac");
console.log(person.name); // 출력: Isaac
person.sayHello(); // 출력: Hello, my name is Isaac
person 객체는 Person 함수로 생성된 객체이다. person 객체에서 name 속성에 접근하면 자신의 속성처럼 사용할 수 있다. 마찬가지로 sayHello 메서드도 자신의 것처럼 호출할 수 있다. 이는 person 객체의 프로토타입 체인을 통해 Person.prototype에 정의된 속성과 메서드를 상속받은 결과이다.
상속
자바스크립트는 프로토타입 체인을 통해 상속을 구현한다.
객체의 프로토타입은 다른 객체를 참조하는데, 이를 이용하여 상위 객체의 속성과 메서드를 하위 객체가 상속받을 수 있다.
아래는 상속을 활용한 예시 소스코드이다.
// 부모 클래스: 차량
class Vehicle {
constructor(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
start() {
console.log(`The ${this.make} ${this.model} starts.`);
}
stop() {
console.log(`The ${this.make} ${this.model} stops.`);
}
}
// 자식 클래스: 전기 자동차
class ElectricCar extends Vehicle {
constructor(make, model, year, range) {
super(make, model, year);
this.range = range;
}
charge() {
console.log(`The ${this.make} ${this.model} is charging.`);
}
}
// 자식 클래스: 가솔린 자동차
class GasolineCar extends Vehicle {
constructor(make, model, year, fuelType) {
super(make, model, year);
this.fuelType = fuelType;
}
refuel() {
console.log(`The ${this.make} ${this.model} is refueling.`);
}
}
// 객체 생성
const tesla = new ElectricCar("Tesla", "Model 3", 2022, 400);
const bmw = new GasolineCar("BMW", "X5", 2021, "Gasoline");
// 객체 메서드 호출
tesla.start();
tesla.charge();
tesla.stop();
bmw.start();
bmw.refuel();
bmw.stop();
Vehicle 클래스는 모든 차량의 부모 클래스이며, ElectricCar 클래스와 GasolineCar 클래스는 Vehicle 클래스를 상속받아 각각의 특징을 추가한다.
ElectricCar 클래스에는 charge 메서드가 추가되어 전기 자동차의 충전 기능을 나타내고, GasolineCar 클래스에는 refuel 메서드가 추가되어 가솔린 자동차의 주유 기능을 나타낸다.
이렇게 상속을 활용하면 공통된 기능을 부모 클래스에서 정의하고, 각 자식 클래스에서는 추가적인 기능을 구현하는 것이 가능해진다.
위 소스코드에서 각 차량이 다른 기능을 가지고 있지만, 공통적으로 start와 stop 메서드를 상속받아 사용하고 있다. 이처럼 공통된 기능을 부모 클래스에서 한 번만 구현하면 자식 클래스에서는 해당 기능을 바로 사용할 수 있게 된다.
각 객체의 메서드 호출에 따라 해당하는 문구가 출력되어 자동차의 동작을 나타내는 결과는 다음처럼 보여진다.
The Tesla Model 3 starts.
The Tesla Model 3 is charging.
The Tesla Model 3 stops.
The BMW X5 starts.
The BMW X5 is refueling.
The BMW X5 stops.
tesla 객체는 ElectricCar 클래스의 인스턴스이므로 start, charge, stop 메서드를 호출할 수 있다. bmw 객체는 GasolineCar 클래스의 인스턴스이므로 start, refuel, stop 메서드를 호출할 수 있다.