생성자함수와 클래스
- 프로토타입
- 생성자함수
- 생성자함수 상속
- 클래스
- 클래스 상속
- 클래스 오버라이딩
- 클래스 get/set
1. Prototype 프로토타입
자바스크립트의 프로토타입(Prototype)은 모든 객체가 상속받는 속성과 메서드를 정의한 객체입니다. 모든 JavaScript 객체는 내부적으로 프로토타입을 가지고 있습니다. 프로토타입은 객체 간의 상속 관계를 정의하고, 객체가 원시적인 값을 가지지 않고 다른 객체를 기반으로 하도록 합니다.
프로토타입은 객체 지향 프로그래밍에서 중요한 개념이며, 상속, 코드 재사용, 객체 지향 디자인 패턴 등을 구현하는 데에 널리 사용됩니다.
- 상속 (Inheritance): 모든 JavaScript 객체는 다른 객체로부터 상속된 속성과 메서드를 가질 수 있습니다. 객체가 특정 속성 또는 메서드를 찾을 때, 해당 속성 또는 메서드가 객체 자체에 정의되어 있지 않으면 그것을 상속받은 프로토타입 체인을 따라 상위 프로토타입에서 찾습니다.
- 프로토타입 기반 (Prototype-based) 객체 지향 프로그래밍: 자바스크립트는 프로토타입 기반의 객체 지향 언어입니다. 클래스가 아닌 프로토타입을 기반으로 객체를 생성하고 상속합니다. 따라서 프로토타입을 활용하여 객체를 생성하고 확장할 수 있습니다.
프로토타입은 모든 객체가 가지고 있는 __proto__ 속성을 통해 접근할 수 있습니다. 또한, ES6에서는 Object.getPrototypeOf() 메서드를 사용하여 객체의 프로토타입에 직접 접근할 수 있습니다.
2. 생성자함수
생성자 함수(Constructor Function)는 객체를 생성할 때 사용되는 함수입니다. 생성자 함수를 사용하면 동일한 구조를 가진 여러 객체를 간편하게 생성할 수 있습니다. 생성자 함수는 일반 함수와 유사하게 정의되지만, 관례적으로 첫 글자를 대문자로 시작하여 이름을 지정합니다.
1. 함수이름의 첫 글자는 대문자로 시작합니다.
2. 반드시 new 연산자를 붙여서 실행합니다.
3. 인스턴스 = new 생성자함수()
new 키워드로 만들어진 객체는 해당 타입의 인스턴스라고 합니다.
인스턴스란 객체에 타입이 적용되면 해당 객체는 그 타입의 인스턴스라고 합니다.
4. this란 자기 자신으로 생성자 함수를 호출한 객체를 의미합니다. ( 인스턴스 )
ex1)
function User(name) {
this.name = name;
this.isDone = false;
this.print = function(){
console.log('출력');
}
}
let user = new User("이젠");
console.log(user.name); // 이젠
console.log(user.isDone); // false
user.print();
ex2)
/ 생성자 함수 정의
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
console.log("안녕하세요, 저는 " + this.name + "이고, " + this.age + "살입니다.");
};
}
// 생성자 함수를 사용하여 객체 생성
var person1 = new Person("John", 30);
var person2 = new Person("Alice", 25);
// 객체 메서드 호출
person1.greet(); // 출력: 안녕하세요, 저는 John이고, 30살입니다.
person2.greet(); // 출력: 안녕하세요, 저는 Alice이고, 25살입니다.
3. 생성자함수 상속
생성자 함수 상속(Constructor Function Inheritance)은 부모 생성자 함수의 프로토타입을 자식 생성자 함수의 프로토타입으로 설정함으로써 구현됩니다. 이를 통해 자식 객체가 부모 객체의 속성과 메서드를 상속받을 수 있습니다.
// 부모 생성자 함수 정의
function Animal(name) {
this.name = name;
}
// 부모 생성자 함수의 프로토타입에 메서드 추가
Animal.prototype.walk = function() {
console.log(this.name + " is walking.");
};
// 자식 생성자 함수 정의
function Dog(name, breed) {
// 부모 생성자 함수 호출하여 상속받은 속성 초기화
Animal.call(this, name);
this.breed = breed;
}
// 자식 생성자 함수의 프로토타입 설정
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 자식 생성자 함수의 프로토타입에 메서드 추가
Dog.prototype.bark = function() {
console.log(this.name + " is barking.");
};
// 객체 생성
var myDog = new Dog("Buddy", "Golden Retriever");
// 부모 메서드 호출
myDog.walk(); // 출력: Buddy is walking.
// 자식 메서드 호출
myDog.bark(); // 출력: Buddy is barking.
Animal 생성자 함수는 동물을 나타내며, walk 메서드를 가지고 있습니다. Dog 생성자 함수는 Animal 생성자 함수를 상속받고, bark 메서드를 추가로 정의합니다.
Object.create 메서드를 사용하여 Dog 생성자 함수의 프로토타입을 Animal 생성자 함수의 프로토타입으로 설정합니다. 이로써 Dog 객체는 Animal 객체의 속성과 메서드를 상속받습니다. 또한, Dog 생성자 함수의 constructor 속성을 다시 Dog로 설정하여 정상적인 생성자를 보장합니다.
이제 myDog 객체는 walk 메서드와 bark 메서드를 모두 호출할 수 있습니다.
4. 클래스
클래스 | mdn |
Classes | mdn |
constructor | mdn |
extends | mdn |
Private class fields | mdn |
static | mdn |
클래스(Class)는 ES6(ECMAScript 2015)에서 도입된 개념으로, 객체 지향 프로그래밍을 지원하기 위한 구조적인 패턴을 제공합니다. 클래스를 사용하면 객체를 생성하고 관리하기 위한 표준화된 방법을 제공하며, 상속, 캡슐화, 다형성 등의 객체 지향 개념을 쉽게 구현할 수 있습니다.
기존에는 프로토타입 기반의 객체 지향 프로그래밍을 사용하여 클래스와 유사한 기능을 구현했지만, ES6에서는 클래스 문법을 제공하여 클래스를 더 직관적이고 편리하게 정의할 수 있게 되었습니다.
클래스를 사용하면 객체 지향 프로그래밍의 개념을 쉽게 적용할 수 있으며, 코드를 구조화하고 재사용성을 높일 수 있습니다.
ES6이후, 자바스크립트는 클래스 기반의 객체 생성을 지원
생성자 함수로 동작하며, 보더 명확하고 이해하기 쉬운 방식으로 객체를 생성
- 클래스는 class 키워드를 사용하여 정의합니다.
- 클래스 이름은 생성자 함수처럼 파스칼 케이스를 사용하는 것이 일반적입니다.
- 클래스가 값으로 사용할 수 있는 일급 객체임을 의미합니다.
- 클래스 안에는 메서드로 constructor(생성자), 프로토타입 메서드, 정적 메서드 세 가지가 있습니다.
- 템플릿(Template): 클래스는 객체를 생성하기 위한 템플릿으로 사용됩니다. 클래스를 정의하면 해당 클래스의 인스턴스를 여러 개 생성할 수 있습니다.
- 상속(Inheritance): 클래스는 상속을 통해 다른 클래스의 속성과 메서드를 상속받을 수 있습니다. 이를 통해 코드의 재사용성을 높일 수 있습니다.
- 캡슐화(Encapsulation): 클래스는 데이터와 데이터를 처리하는 메서드를 하나의 단위로 묶어 캡슐화를 제공합니다. 이를 통해 데이터의 접근을 제어하고 보호할 수 있습니다.
- 다형성(Polymorphism): 클래스는 다형성을 지원합니다. 이는 동일한 메서드를 다양한 방식으로 구현할 수 있고, 각각의 객체에서 다르게 동작할 수 있음을 의미합니다.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
형식
// 계산기 클래스 정의
class Calculator {
// 생성자 메서드
constructor() {
this.result = 0;
}
// 덧셈 메서드
add(value) {
this.result += value;
}
// 뺄셈 메서드
subtract(value) {
this.result -= value;
}
// 곱셈 메서드
multiply(value) {
this.result *= value;
}
// 나눗셈 메서드
divide(value) {
if (value !== 0) {
this.result /= value;
} else {
console.error('0으로 나눌 수 없습니다.');
}
}
// 결과 출력 메서드
printResult() {
console.log('결과:', this.result);
}
}
// 계산기 객체 생성
const calc = new Calculator();
// 계산 수행
calc.add(10);
calc.subtract(5);
calc.multiply(2);
calc.divide(4);
// 결과 출력
calc.printResult(); // 출력: 결과: 5
Calculator 클래스를 정의하여 간단한 사칙연산 계산기를 구현하였습니다. 생성자 메서드를 사용하여 result 속성을 초기화하고, 덧셈, 뺄셈, 곱셈, 나눗셈 등의 메서드를 추가로 정의하였습니다. 이후에는 클래스의 인스턴스를 생성하여 각 메서드를 호출하여 계산을 수행하고, printResult 메서드를 사용하여 최종 결과를 출력합니다.
// 클래스 선언문
class Person {
// 클래스 필드 정의
hak = "A"
// 생성자
constructor(name) {
//this는 클래스가 생성한 인스턴스 자기자신 => test
this.name = name;
}
// 프로토타입 메서드
print() {
console.log(`출력 ${this.name}`);
}
// 정적 메서드
static hi() {
console.log("Hello!")
}
}
// 인스턴스 생성
const test = new Person("이젠");
// 인스턴스의 프로퍼티 참조
console.log(test.name);
// 프로토타입 메서드 호출
test.print();
//정적 메서드 호출
Person.hi();
console.log(test instanceof Person); // true
console.log(test instanceof Object); // true
# 상속에 의한 클래스 확장
- extends 키워드 사용
- 상속에 의한 클래스 확장은 기존 클래스를 상속받아 새로운 클래스를 확장하여 정의하는 것.
- 상속을 통해 확장된 클래스를 서브클래스라 부르고, 서브클래스에 상속된 클래스를 슈퍼클래스라고 함
- 서브 클래스는 파생 클래스, 자식 클래스라고 하고 슈퍼클래스는 베이스 클래스 부모 클래스라고 부르기도 함
- extends 키워드의 역할은 슈퍼클래스와 서브클래스 간의 상속 관계를 설정하는 것
- 프로토타입 메서드, 정적 메서드 모두 상속 가능 (자손은 조상의 모든 프로퍼티를 상속 )
- 하위클래스가 상위클래스를 상속받았을 때 하위클래스는 상위클래스의 모든 권한을 갖게 됨.
- 상속개념을 적용하면 재사용성을 높이고 관리가 용이.
- 단일 상속 개념 - 상속받을 수 있는 클래스는 단 하나
// 클래스 정의
class Animal {
// 생성자 메서드
constructor(name) {
this.name = name;
}
// 메서드 정의
speak() {
console.log(this.name + " makes a noise.");
}
}
// 클래스 상속
class Dog extends Animal {
// 생성자 메서드 오버라이드
constructor(name) {
super(name); // 부모 클래스의 생성자 호출
}
// 메서드 오버라이드
speak() {
console.log(this.name + " barks.");
}
}
// 객체 생성
const dog = new Dog('Buddy');
dog.speak(); // 출력: Buddy barks.
Animal 클래스와 Dog 클래스를 정의하고 있습니다. Dog 클래스는 Animal 클래스를 상속받아 speak 메서드를 오버라이드하여 재정의하고 있습니다. 클래스를 사용하면 객체 지향 프로그래밍의 개념을 더 효율적으로 구현할 수 있으며, 코드의 가독성과 유지 보수성을 향상할 수 있습니다.
// 동물 클래스 정의
class Animal {
constructor(name) {
this.name = name;
}
// 소리를 내는 메서드
speak() {
console.log(this.name + ' makes a noise.');
}
}
// 개 클래스 정의 (동물 클래스를 상속)
class Dog extends Animal {
// 개별적인 생성자
constructor(name) {
// 부모 클래스의 생성자 호출
super(name);
}
// 개의 소리 메서드를 오버라이드
speak() {
console.log(this.name + ' barks.');
}
}
// 고양이 클래스 정의 (동물 클래스를 상속)
class Cat extends Animal {
constructor(name) {
super(name);
}
// 고양이의 소리 메서드를 오버라이드
speak() {
console.log(this.name + ' meows.');
}
}
// 객체 생성
const dog = new Dog('Buddy');
const cat = new Cat('Whiskers');
// 객체 메서드 호출
dog.speak(); // 출력: Buddy barks.
cat.speak(); // 출력: Whiskers meows.
Animal 클래스는 모든 동물을 나타내며, speak 메서드를 가지고 있습니다. Dog 클래스와 Cat 클래스는 각각 개와 고양이를 나타내는데, 이들 클래스는 Animal 클래스를 상속받아 speak 메서드를 오버라이드하여 개와 고양이의 소리를 나타냅니다.
Dog와 Cat 클래스에서는 super 키워드를 사용하여 부모 클래스의 생성자를 호출하고 있습니다. 이를 통해 부모 클래스의 초기화를 수행하고 자식 클래스에서 추가적인 초기화를 할 수 있습니다.
이렇게 JavaScript에서는 extends 키워드를 사용하여 클래스 간에 상속 관계를 정의할 수 있습니다. 상속을 사용하면 코드의 재사용성을 높이고 객체 지향 프로그래밍의 개념을 쉽게 적용할 수 있습니다.
# super 키워드
super 키워드는 클래스 내에서 부모 클래스의 메서드를 호출하거나 부모 클래스의 생성자를 참조할 때 사용됩니다. super를 사용하여 부모 클래스의 메서드를 호출하면, 해당 메서드는 현재 클래스의 인스턴스에서 실행됩니다.
- 부모 클래스의 생성자 호출: 자식 클래스의 생성자에서 부모 클래스의 생성자를 호출할 때 사용됩니다. 이렇게 하면 자식 클래스에서 초기화 작업을 수행하기 전에 부모 클래스의 초기화 작업이 먼저 실행됩니다.
- 부모 클래스의 메서드 호출: 자식 클래스에서 부모 클래스의 메서드를 호출할 때 사용됩니다. 이를 통해 자식 클래스에서 부모 클래스의 메서드를 확장하거나 오버라이드할 수 있습니다.
- super 키워드는 함수처럼 호출할 수도 있고 this와 같이 식별자처럼 참조할 수 있는 특수 키워드
- super를 호출하면 슈퍼클래스의 constructor(super-constructor)를 호출
- super를 참조하면 수퍼클래스의 메서드를 호출
형식)
class 부모 {
constructor(name) {
this.name = name;
}
}
class 자식 extends 부모 {
constructor(name) {
super(name)
}
constructor( ...rest ) {
super( ...rest )
}
}
# 부모 클래스의 생성자 호출
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 부모 클래스의 생성자 호출
this.breed = breed;
}
speak() {
super.speak(); // 부모 클래스의 메서드 호출
console.log(this.name + ' barks.');
}
}
const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak();
// 출력:
// Buddy makes a noise.
// Buddy barks.
# 부모 클래스의 메서드 호출
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
speak() {
super.speak(); // 부모 클래스의 메서드 호출
console.log(this.name + ' barks.');
}
}
const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak();
// 출력:
// Buddy makes a noise.
// Buddy barks.
메서드의 오버로딩(Overloading)
자바스크립트는 전통적인 객체 지향 언어인 자바와는 달리 메서드의 오버로딩(overloading)이나 클래스의 오버라이딩(overriding)을 명시적으로 지원하지는 않습니다. 하지만, 메서드의 오버로딩과 클래스의 오버라이딩과 비슷한 기능을 구현할 수 있습니다.
메서드의 오버로딩(Overloading)
메서드 오버로딩은 같은 이름을 가진 메서드가 여러 개 정의되어 다양한 매개변수를 받을 수 있도록 하는 것을 의미합니다. 자바스크립트는 메서드 오버로딩을 명시적으로 지원하지 않습니다. 대신에 함수의 매개변수를 유연하게 다룰 수 있도록 함수 내부에서 매개변수를 체크하고 처리할 수 있습니다. 예를 들어, 함수 내부에서 전달된 매개변수의 타입이나 개수를 확인하여 다른 동작을 수행하도록 조건문을 활용할 수 있습니다.
function exampleFunction(a, b) {
if (typeof a === 'number' && typeof b === 'number') {
// 두 개의 숫자를 받아 처리하는 경우
return a + b;
} else if (typeof a === 'string' && typeof b === 'string') {
// 두 개의 문자열을 받아 처리하는 경우
return a.concat(b);
} else {
// 다른 경우 처리
return 'Unsupported argument types';
}
}
console.log(exampleFunction(2, 3)); // 출력: 5
console.log(exampleFunction('Hello', 'World')); // 출력: HelloWorld
console.log(exampleFunction(true, false)); // 출력: Unsupported argument types
클래스의 오버라이딩(Overriding)
클래스 오버라이딩은 부모 클래스의 메서드를 자식 클래스에서 다시 정의하는 것을 의미합니다. 이렇게 하면 자식 클래스에서 부모 클래스의 메서드를 재정의하여 자식 클래스의 특정 동작을 수행하도록 할 수 있습니다.
class Animal {
speak() {
console.log('동물이 소리를 냅니다.');
}
}
class Dog extends Animal {
speak() {
console.log('개가 짖습니다.');
}
}
const animal = new Animal();
const dog = new Dog();
animal.speak(); // 출력: 동물이 소리를 냅니다.
dog.speak(); // 출력: 개가 짖습니다.
Animal 클래스의 speak 메서드를 Dog 클래스에서 오버라이딩하여 새로운 동작을 정의했습니다. 따라서 dog.speak()를 호출하면 Dog 클래스의 speak 메서드가 실행됩니다.
요약하면, 메서드 오버로딩은 같은 이름의 메서드가 다양한 매개변수를 받을 수 있도록 하는 것을 의미하고, 클래스 오버라이딩은 부모 클래스의 메서드를 자식 클래스에서 재정의하는 것을 의미합니다. JavaScript에서는 메서드 오버로딩을 명시적으로 지원하지 않지만, 유연한 함수 정의를 통해 비슷한 기능을 구현할 수 있습니다. 클래스 오버라이딩은 자바스크립트의 클래스 상속을 통해 구현할 수 있습니다.
# get, set
접근자 프로퍼티 자체적으로 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티입니다.
접근자란 객체 지향 프로그래밍에서 객체가 가진 프로퍼티 값을 객체 바깥에서 읽거나 쓸 수 있도록 제공하는 메서드입니다.
set과 get은 클래스 내에서 속성 값을 설정하고 가져오는 데 사용됩니다. 이들은 클래스 내에 정의된 메서드로, 속성에 값을 할당하거나 속성 값을 가져올 때 자동으로 호출됩니다.
- set 메서드:
- set 메서드는 속성에 값을 할당할 때 호출되는 메서드입니다.
- 일반적으로 set 메서드는 클래스 내에서 속성 값을 설정하기 위해 사용됩니다.
- set 메서드는 set 키워드 뒤에 속성 이름을 지정하여 정의됩니다.
- set 메서드는 단일 매개변수를 받아 속성에 할당할 값을 전달받습니다.
- get 메서드:
- get 메서드는 속성 값을 가져올 때 호출되는 메서드입니다.
- 일반적으로 get 메서드는 클래스 내에서 속성 값을 가져오기 위해 사용됩니다.
- get 메서드는 get 키워드 뒤에 속성 이름을 지정하여 정의됩니다.
- get 메서드는 속성 값을 반환하는 데 사용됩니다. 이 메서드는 어떤 인자도 받지 않습니다.
- get
메서드 이름 앞에 get 키워드를 사용해 정의
getter는 호출하는 것이 아니라 프토퍼리처럼 참조하는 형식으로 사용하며, 참조 시 내부적으로 getter가 호출
getter는 반드시 무언가를 반환
setter는 인스턴스 프로퍼티에 값을 할당할 때마다 프로퍼티 값을 조작하거나 별도의 행위가 필요할 때 사용
- set
setter는 호출하는 것이 아니라 프로퍼티처럼 값을 할당하는 형식으로 사용하며, 할당 시에 내부적으로 setter가 호출
setter는 무언가를 프로퍼티에 할당해야 하므로 매개변수가 있어야 함
(단 하나의 값만 할당받으므로 하나의 매개변수만 선언)
class Person {
constructor(name) {
this.name = name;
}
get name() {
return this._name;
}
set name(newName) {
newName = newName.trim();
this._name = newName;
}
}
class Person{
constructor(name, age) {
this.name = name;
this.age = age;
}
get name() {
return this._name.toUpperCase();
}
set name(newName){
if(newName){
this._name = newName;
}
}
}
let man = new Person('hi', 30);
console.log(man.name, man.age);
class Rectangle {
constructor(width, height) {
this._width = width;
this._height = height;
}
// set 메서드 정의
set width(value) {
if (value > 0) {
this._width = value;
} else {
console.error('너비는 0보다 커야 합니다.');
}
}
// get 메서드 정의
get width() {
return this._width;
}
// set 메서드 정의
set height(value) {
if (value > 0) {
this._height = value;
} else {
console.error('높이는 0보다 커야 합니다.');
}
}
// get 메서드 정의
get height() {
return this._height;
}
// 사각형의 넓이를 계산하는 메서드
calculateArea() {
return this._width * this._height;
}
}
// Rectangle 클래스의 인스턴스 생성
const rectangle = new Rectangle(5, 10);
// 속성 값 설정하기 (set 메서드 호출)
rectangle.width = 7;
rectangle.height = 12;
// 속성 값 가져오기 (get 메서드 호출)
console.log('너비:', rectangle.width);
console.log('높이:', rectangle.height);
// 사각형의 넓이 계산하기 (calculateArea 메서드 호출)
console.log('넓이:', rectangle.calculateArea());
Rectangle 클래스는 width와 height 속성을 가지고 있습니다. set 메서드를 사용하여 속성 값을 설정하고 get 메서드를 사용하여 속성 값을 가져오고 있습니다. 이를 통해 속성 값을 쉽게 조작하고 접근할 수 있습니다.
# static 필드
class Item {
static count = 0;
static getCount() {
return Item.count;
}
}
console.log(Item.getCount()); // 0
# 비공개 필드 : private 필드
자바스크립트는 완전하게 캡슐화를 지원하지 않음. (인스턴스 프로퍼티는 언제나 public)
2021년 1월 기준 TC39 프로세스 stage 3(candidate)에서 private 필드 정의할 수 있는 새로운 표준 사양이 제안 (최신 브라우저 및 Node 버전에선 이미 구현되어 있음)
private 필드의 앞에 #을 붙여주며, 참조 시에도 #을 붙여줘야 함
class Person {
//private 필드 정의
#name = ""
constructor(name) {
//private 필드 참조
this.#name = name
}
}
const test = new Person("홍길동")
// private 필드 #name은 클래스 외부에서 참조할 수 없음.
console.log(test.#name)
// SyntaxError: Private field '#name' must be declared in an enclosing class
class Person {
//private 필드 정의
#name = ""
constructor(name) {
this.#name = name
}
// name은 접근자 프로퍼티다.
get name() {
// private 필드를 참조하여 trim한 다음 반환한다.
return this.#name.trim()
}
}
const test = new Person(" 홍길동 ")
console.log(test.name)
클래스 은닉
클래스의 은닉(Encapsulation)은 외부에서 클래스의 내부 상태를 직접 접근할 수 없도록 하는 것을 의미합니다. 이를 통해 클래스의 내부 구현을 보호하고, 외부에서 클래스의 내부 상태를 직접 변경하는 것을 방지할 수 있습니다.
자바스크립트에서 클래스의 은닉을 달성하는 방법은 주로 클로저(Closure)를 사용하거나 프로퍼티 이름을 통한 관례를 활용하는 방식이 있습니다.
클로저를 사용한 은닉
클로저를 사용하여 클래스의 은닉을 구현할 수 있습니다. 이 방법은 클래스의 속성을 비공개(private)로 만들고, 외부에서는 해당 속성에 직접 접근할 수 없도록 합니다.
class Counter {
constructor() {
let count = 0;
this.increment = function() {
count++;
};
this.decrement = function() {
count--;
};
this.getCount = function() {
return count;
};
}
}
const counter = new Counter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 출력: 2
count 변수는 생성자 함수 내부에 선언되어 있으므로 외부에서 직접 접근할 수 없습니다. 대신에 increment, decrement, getCount 메서드를 통해 간접적으로 접근할 수 있습니다.
프로퍼티 이름을 통한 은닉
또 다른 방법은 프로퍼티 이름을 통한 관례를 사용하여 은닉을 구현하는 것입니다. 이 방법은 속성 이름 앞에 언더스코어(_)를 붙이는 관례를 따르면 됩니다. 이러한 속성은 외부에서 접근하는 것이 일반적으로 지양되지만, 완전히 숨겨지지는 않습니다.
class Counter {
constructor() {
this._count = 0;
}
increment() {
this._count++;
}
decrement() {
this._count--;
}
getCount() {
return this._count;
}
}
const counter = new Counter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 출력: 2
_count는 클래스의 외부에서 접근할 수 있지만, _로 시작하는 네이밍 관례를 따르므로 외부에서 직접적으로 접근하는 것은 지양됩니다.
클로저와 네이밍 관례를 혼합하여 클래스의 은닉을 보다 강력하게 구현할 수도 있습니다. 이러한 방식으로 클래스의 내부 상태를 보호하고 캡슐화하여 안정성을 높이고, 의도치 않은 변경으로부터 보호할 수 있습니다.
'javascript+es6' 카테고리의 다른 글
[ javascript ] 24. window.localStorage (0) | 2023.11.28 |
---|---|
[ javascript ] 23. 모듈 (0) | 2023.11.15 |
[ javascript ] 21. 비구조화 할당 (구조분해) 문법 (0) | 2023.11.09 |
[ javascript ] 20. 얕은 복사 VS 깊은 복사 (0) | 2023.11.08 |
[ javascript ] 19. Object , JSON, Spread연산자, 나머지연산자, 옵셔널 체이닝 (0) | 2023.11.07 |