[새싹 프론트엔드] 4주차 - 3
객체와 클래스
• 객체(Object)
실생활에 존재하는 실제적인 물건 또는 개념
• 속성(Attribute) = 변수
객체가 가지고 있는 특성
• 메서드(Method) = 함수
객체가 동작(행동)할 수 있도록 하는 함수
- 메서드 안에는 함수만 담기
클래스 (es6 버전에서 새롭게 생김)
• 객체가 가져야 할 기본적인 정보를 담은 코드
• 객체를 효율적으로 생성하기 위해 만들어진 구문 ( 일종의 설계도 )
겉모습은 똑같아도 안에 담는 재료는 다다르다
틀은 붕어빵을 만들기 위한 설계도
클래스가 있으면 붕어빵을 쉽게 만들 수 있당
중복되는 코드들을 모아가지고 갖고있음 - 생성자 함수랑 같음
생성자 함수 vs 클래스
생성자 함수
• new 키워드가 생략되면 일반 함수로 호출됨
• function 키워드로 정의
클래스
• new 키워드 생략 시, 타입 에러 발생
• class 키워드로 정의
클래스 선언 및 객체 생성
function과 달리 소괄호 사용하지 않음 중괄호만 사용
첫글자는 대문자로!!
class 붕어빵 틀{ }
클래스 함수
클래스 내부 함수 종류
• 생성자 메서드
• 프로토타입 메서드
• 정적 메서드
생성자 메서드
객체를 생성하고 초기화하는 메서드
• 변수의 값을 정의
• 클래스 내에 최대 1개만 존재
• 생략 가능 (기왕이면 만들어주자)
• 생략 시, 빈 생성자가 만들어짐 (매개변수가 없을 때에만 생략가능 있다면 무조건 만들어야댐!)
예시)
클래스 외부에서 객체의 초기 프로퍼티 값 전달
생성자 메서드의 return문
• return문은 생략 해야 함
→ new 연산자가 클래스와 함께 호출되면 암묵적으로 객체를 반환해주기 때문
• 명시적으로 객체를 리턴하는 경우
• 명시적으로 다른 값을 반환하는 경우 - (출력x)
생서자 함수의 목적은 객채 초기화
실습) 클래스로 객체 생성하기
객체 값 사용하기
실습 ) 객체 값 콘솔에 출력하기
결과)
프로토타입 메서드
- 클래스 내부에서 명시적으로 정의한 메서드
프로토타입 메서드 호출
프로토타입 메서드 - 화살표 함수
정적 메서드
정적 프로퍼티와 정적 메서드
• 클래스 자체에 선언된 프로퍼티 또는 메서드
• 객체를 생성하지 않아도 호출 가능
(예 - Meth.random)
• 선언 방법
• static 키워드를 붙여서 생성 (주로 프로토타입 메서드를 사용할 것임)
static 붙은 애는 constructor안에 있으면 안 됨
정적 메서드 호출
• 객체가 호출하지 않고, 클래스로 호출해야 함
• 클래스.정적메소드()
function 대신 사용하는 함수 (호출하기 위해)
프로토타입 메서드와의 차이
구분 | 정적 메서드 | 프로토타입 메서드 |
프로토타입 체인 | 클래스 | 인스턴스 |
호출 방식 | 클래스 호출 | 인스턴스로 호출 |
인스턴스 프로퍼티 참조 가능 여부 |
불가능 | 가능 |
실습) 정적 메서드
접근 제어
클래스 접근 제어(캡슐화)
캡슐화(Encapsulation)
- 클래스 내부의 특정 프로퍼티나 메소드를 외부에서 참조하지 못하도록 숨기는 것
• 클래스 외부
제한된 접근 권한을 제공
• 클래스 내부
원하지 않는 외부의 접근에 대해 내부를 보호
• 방법
캡슐화를 원하는 프로퍼티나 메서드 앞에 # 기호를 붙임
1. 첫번째 방식 - 일반적으로 호출
결과 - #color 변수는 rec1.color 방식으로 접근 불가
2. 두번째 방식 - 앞에 #을 붙이는 방식
결과 - 에러 : SyntaxError: Private field '#color' must be declared in an enclosing class
3. 세번째 방식 - 변수만 호출
결과 - Rectangle { width: 100, height: 200, area: [Function: area] }
이 세가지 방법들로는 클래스로부터 만든 프라이빗 필드나 프라이빗 메서드에 접근할 수 없다.
따라서 안에 있는 값 바꾸려면 접근자 프로퍼티를 써야 한다.
접근자 프로퍼티
데이터 프로퍼티
• 키와 값으로 구성된 일반적인 프로퍼티
접근자 프로퍼티
• 자체적으로는 값을 갖지 않고 다른 데이터 프로퍼티의 값 을 읽거나 저장할 때 호출되는 접근자 함수로 구성된 프로퍼티
종류 | 설명 |
get | • 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수 • getter 함수가 호출되고 그 결과가 프로퍼티 값으로 반환 |
set | • 접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장 할 때 호출되는 접근자 함수 • setter 함수가 호출되고 그 결과가 프로퍼티 값으로 저장 |
getter 함수
• get 키워드로 선언
• 호출 방법
함수 호출 방식이 아닌 프로퍼티 호출 방식으로 호출
외부에서 접근 못할 때 get만 붙이면 접근 가능해짐(값을 우회해서 접근할 수 있게 함)
그냥 display() 하면 원하는 결과 안 나옴
setter 함수
외부에서 값을 들고감
• set 키워드로 선언
• 값 저장 방법
값 할당 방식으로 저장
값을 바꾸고 싶으면 set 사용
get/set 함수
호출 방법 : 객체이름.함수
실습) 접근자 프로퍼티 -1
결과)
실습) 접근자 프로퍼티 -2
결과)
상속
클래스 상속
- 한 클래스가 다른 클래스에서 정의된 속성 및 함수를 물려 받아 그대로 사용 (코드재사용)
- 상속 받아 만들어진 클래스의 특징
• 물려받은 기능에 필요한 기능을 추가하여 정의할 수 있음
클래스 상속 방법
실습) 클래스 상속
부모 클래스
자식 클래스
실습) 클래스 상속
부모꺼 모조리 싹 다 물려받아서 speak도 출력됨
오버라이딩(overriding)
- 부모 클래스로부터 상속받은 메서드를 자식 클래스에서 재정의
※ 오버로딩 : 매개변수 갯수가 다름
instanceof 연산자
객체가 특정 클래스에 속하는지 아닌지를 확인해주는 연산자
• 해당하면 true 리턴
• 해당하지 않으면 false 리턴
cat클래스 없어서 에러남 사실 그래서 cat을 만들어놓고 extends Animal을 안해놔야됨
[실습회고]
이번 실습은 한마디로 "쉽지 않다.."
일단 숨참고 실습 다이브 했는데 말이죠 한 문제를 무슨 2시간동안 붙잡고있었는데 어디서부터 어디까지 틀리고 맞았는지도 모르겠고 클래스를 제대로 쓰고 있는 건지도 모르겠어서 진짜 길을잃었다,,, 그래서 선생님의 도움을 받았다!
정말 모르겠는 건 도움을 받아야 하는 게 맞는거니까 ^-^
일단 먼저 클래스와 객체에 대한 개념부터 다시 잡았다. 클래스는 틀 생성자랑 비슷하고 객체는 정말 붕어빵처럼 얼마든지 맛만 다른 (모양은 같은) 것들을 찍어낼 수 있는 것으로 일단 틀을 먼저 잘 잡아야 한다. 객체 안에는 속성(=변수)과 메서드 (함수)가 있는데 이 객체를 생성하기 위해서는 반드시 blabla = new blabla2() 요런식으로 써줘야 한다. 호출도 그냥 하는게 아니라 blabla.함수 () 이렇게 해야 호출이 됨. 그리고 클래스 안에 함수들을 만들어서 클래스 밖에서 그 함수들을 호출하여 결과값을 내도록 해야 한다. 역시 말보단 코드! 코드를 보면 한 방에 이해감
1번문제
<body>
<script>
class Goodstock {
constructor(code, stock) {
this.code = code;
this.stock = stock;
}
print() {
return `상품코드 : ${this.code} \n 재고수량 : ${this.stock}`;
}
addstock(inputadd) {
this.stock += inputadd;
}
}
code = prompt("상품코드를 입력하세요");
stock = parseInt(prompt("재고수량을 입력하세요"));
goodstock = new Goodstock(code, stock);
alert(goodstock.print());
inputadd = parseInt(prompt("추가할 수량을 입력하세요"));
goodstock.addstock(inputadd);
document.write("상품코드 : " + goodstock.code + "<br>");
document.write("재고수량 : " + goodstock.stock);
// document.write(goodstock.print());
</script>
클래스 안에 있는 프로퍼티나 함수들을 호출하려면 this. 을 앞에 꼬옥 붙여줘야함 !!
함수명과 매개변수를 헷갈리지 말자 ,, 이래서 명 지을 때 다들 심란해하는거구만,,
아 맞아 함수 안에서는 줄바꿈 하려면 \n 이거 써줘야 한다는 것을 첨 알았다 하나하나 늘어가는 코딩지식 ㅎ
2번문제
이거는 1번 문제를 이해한 후 1번보단 비교적 쉽게 풀었는데 출력하는 거를 함수로 만들어서 할 생각을 못해서 한참 만지작 거렸음. 출금이랑 입금이 있으니까 틀은 만들어두고 객체만 다르게 해서 생성하면되지롱
그래서 출력할 때도 매개변수에 입금값 출금값 넣어서 하먄댐 근데 난 이걸 한참을 만지작 거리다가 귤님 조언듣고 깨달음 ㅎㅎ 역시 클래스는 어려워
<body>
<script>
class Account {
constructor(accountNo, ownerName, balance) {
this.accountNo = accountNo;
this.ownerName = ownerName;
this.balance = balance;
}
deposit(구멍) {
this.balance += 구멍;
}
withdraw(멍구) {
this.balance -= 멍구;
}
displayAccount() {
document.write(`계좌번호 : ${this.accountNo}<br>`);
document.write(`예금주 이름 : ${this.ownerName}<br>`);
document.write(`잔액 ${this.balance} <hr>`);
}
}
let obj1 = new Account("111 - 222 - 3333333", "정수아", 50000);
obj1.deposit(100000);
let obj2 = new Account("555 - 666 - 7777777", "손이안", 100000);
obj2.withdraw(30000);
obj1.displayAccount(obj1);
obj2.displayAccount(obj2);
</script>
</body>
3번문제
마지막에 출력이 잘 안되서 애먹다가 집단지성을 빌려 해결함
내가 함수 사용하고 reture을 안써줘서 자꾸 undefined가 떴던 것 ㅎ 잘 해결 완
<body>
<script>
class FourCal {
constructor(num1, num2) {
this.num1 = num1;
this.num2 = num2;
}
add() {
return this.num1 + this.num2;
}
sub() {
return this.num1 - this.num2;
}
mul() {
return this.num1 * this.num2;
}
div() {
return this.num1 / this.num2;
}
display() {
document.write(`두 수를 더한 값 : ${this.add()}<br>`);
document.write(`두 수를 뺀 값 : ${this.sub()}<br>`);
document.write(`두 수를 곱한 값 : ${this.mul()}<br>`);
document.write(`두 수를 나눈 값 : ${this.div()}<br>`);
}
}
num1 = parseInt(prompt("첫 번째 숫자를 입력하세요"));
num2 = parseInt(prompt("두 번째 숫자를 입력해주세요"));
let cal = new FourCal(num1, num2);
cal.display();
</script>
'새싹DT 기업연계형 프론트엔드 실무 프로젝트 과정 2주차 블로그 포스팅'