메서드 호출은 객체.메서드()
같이 객체 내에 메서드를 호출하는 방법을 의미
(메서드 호출 방식은 화살표 함수를 쓰지 않음!!)
클로저 모듈 패턴
을 이용하면 똑같은 기능을 하는걸 여러개 만들지 않고, 하나로 재사용하기
// 하나의 객체만 만들 수 있는데 만약 똑같은 기능을 하는 카운터가 여러 개 필요하면,
// 그대로 복붙해야되니 재사용성이 떨어짐
let counter1 = {
value: 0,
increase: function() {
this.value++ // 메서드 호출을 할 경우, this는 counter1을 가리킵니다
},
decrease: function() {
this.value--
},
getValue: function() {
return this.value
}
}
counter1.increase() // console.log(counter1.value) // 1
counter1.increase() // console.log(counter1.value) // 2
counter1.increase() // console.log(counter1.value) // 3
counter1.decrease() // console.log(counter1.value) // 2
counter1.getValue() // 2
////////////////////////////////////////////////////////
// 클로저 모듈 패턴
// 똑같은 기능을 하는걸 여러개 만드는 방법 중 하나
function makeCounter() {
let value = 0;
return {
increase: function() {
value++;
},
decrease: function() {
value--;
},
getValue: function() {
return value;
}
}
}
let counter1 = makeCounter()
counter1.increase()
counter1.getValue() // 1
let counter2 = makeCounter()
counter2.decrease()
counter2.decrease()
counter2.getValue() // -2
객체 지향 프로그래밍은
하나의 모델이 되는 청사진(blueprint)를 만들고, ⇒ class
그 청사진을 바탕으로 한 객체를 만든다. ⇒ instance
//ES5 ) 함수로 정의할 수 있다.
function Car(brand, name, color) {
// 인스턴스가 만들어질 때 실행되는 코드
}
//ES6 ) class 라는 키워드를 사용해 정의할 수 있다.
class Car {
constructor(brand, name, color) {
// 인스턴스가 만들어질 때 실행되는 코드
}
}
constructor
: 생성자 함수로, 인스턴스가 만들어질 때 실행되는 코드이며 return 값을 만들지 않는다.new
키워드 통해 클래스의 새로운 인스턴스를 만들 수 있다.
인스턴스 생성 즉시 생성자 함수(constructor)가 실행되며,
변수에 클래스의 설계를 가진 새로운 객체(인스턴스) 가 할당
각각의 인스턴스는 클래스의 고유한 속성과 메소드를 갖게 된다.
클래스에 속성과 메소드를 정의하고, 인스턴스에서 사용한다.
속성
메서드
ES5의 메서드와 ES6의 메서드는 다른데,
ES5에서의 this.notice = function(name){...} 과
Person.prototype.notice = function(name) {...} 은 다르다
this.notice = function(name){ // 메서드
alert(this.name);
}
Person.prototype.notice = function(name){ // 메서드
alert(this.name);
}
위의 notice 메서드를 가지고 있는 클래스를 a인스턴스와 b인스턴스에 할당됐을 때?
각각 다른 주소값을 가지는 notice가 되어서
a.notice === b.notice 는 false 가 나오고
아래의 notice 메서드를 가지고 있는 클래스를 c인스턴스와 d인스턴스에 할당했을 땐
prototype.notice 라는 주소값?을 c.notice 와 d.notice 가 같이 바라보고 있어서 c.notice === d.notice 는 true 가 나온다.
(라고 나는 이해했따..ㅎ_ㅎ)
클래스에 정의할 수 있는 프로퍼티
클래스 내부에 키(프로퍼티 이름) = 값
형식으로 작성할 수 있고,
객체.키
로 접근이 가능하다
class User {
name = "moon";
age = "secret";
}
const newUser = new User();
console.log(newUser.name); // moon
console.log(newUser.age); // secret
// 생성자 함수(ES5 클래스 작성 문법)사용
function Person(name){
this.name = name; // 속성
Person.prototype.notice = function(name){ // 메서드
alert(this.name);
}
}
// class 키워드(ES6 문법) 사용
class Person{
constructor(name){
this.name = name; // 속성
}
notice(){ // 메서드
alert(this.name);
}
}
일반적인 다른 함수와 구분하기 위해 클래스는 보통 대문자로 시작하며 일반명사로 만들고 일반적인 함수는 적절한 동사를 포함하고 소문자로 시작한다.
this.name=name => this(만들어진 인스턴스에) name이라는 속성을 부여함
new 키워드
로 위에서 만든 클래스의 새로운 인스턴스를 만들면
let 혜린 = new Person('혜린')
두 코드의 실행을 통해 아래와 같은 결과가 나온다.
console.log(혜린.name) // 혜린
혜린.notice(); // alert가 발생 '혜린' 출력
prototype
: 모델의 청사진을 만들 때 쓰는 원형 객체constructor
: 인스턴스가 초기화될 때 실행하는 생성자 함수this
: 함수가 실행될 때, 해당 scope 마다 생성되는 고유한 실행context클래스의 필드는 public, private 두가지 타입으로 생성할 수 있는데
기본값은 public 으로 클래스의 내외부 어디서든 접근이 가능하다.
private 타입은 클래스 외부에서 접근할 수 없는 필드로
프로퍼티 이름 앞에 #
을 붙여 작성할 수 있다.
class User {
name = "moon";
#age = "secret";
printAge() {
console.log(this.#age);
}
}
const newUser = new User();
console.log(newUser.name); // moon
console.log(newUser.age); // undefined
newUser.printAge(); // secret
클래스 외부에서 private 설정한 프로퍼티에 접근할 수 없지만(undefined 노출)
클래스 내부에서 접근이 가능하기 때문에 printAge()
를 통해 사용 가능
인스턴스 없이 사용할 수 있는 프로퍼티나 메서드를 정적 프로퍼티, 메서드 라고 하고
static
키워드를 붙여 작성 가능
(클래스에서 프로퍼티와 메서드를 사용하기 위해 반드스 클래스를 인스턴스화(new) 해서 객체로 만들었는데, 이건 그 프로퍼티와 메서드가 클래스에 연결된 상태이기 때문)
class User {
static hi() {
console.log('hi')
}
}
User.hi();
⇒ 정적 프로퍼티와 메서드는 어떤 특정 객체에 속하는 것이 아니라 전체 클래스에 속하는 함수나 값을 구현할 때 주로 활용
기존의 클래스에 기능을 추가, 재정의 등 클래스를 확장하여 기존의 클래스를 기반으로 새로운 클래스를 만든다는 개념
class Car {
type = 'car';
greeting() {
console.log('hi')
}
}
class Mini extends Car {
brand = 'bmw'
}
const aBmwCar = new Mini();
console.log(aBmwCar.type); // car
console.log(aBmwCar.brand); // bmw
aBmwCar.greeting(); // hi
⇒ Car 클래스를 상속받은 Mini라는 새로운 클래스를 작성하고, Mini 클래스에 객체를 생성
클래스를 상속받을 때 extends
키워드를 사용하며, Mini 는 Car를 상속받아 type 과 greeting() 메서드에 접근할 수 있음
constructor(생성자 함수) 를 오버라이딩 할 때 부모의 생성자 함수를 호출하는
super()
를 호출해서 해결할 수 있다.
그러면 부모클래스의 constructor 와 오버라이딩한 constructor 가 모두 실행된다.
⇒ 부모, 자식 클래스의 생성자 함수가 순서대로 실행
만약 constructor 에서 인자를 요구한다면,
super()
에도 인자를 지정해 줘야 한다
class Car {
constructor(name) {
this.name = name;
}
}
class Mini extends Car {
constructor(name, brand) {
super(name);
this.brand = brand;
}
}
const aBmwCar = new Mini('mini', 'bmw');
console.log(aBmwCar.name); // car
console.log(aBmwCar.brand); // bmw