일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 자바의 정석(기초편)
- Spring Framework
- softeer
- 코딩테스트
- Programming
- BFS
- MySQL
- 영어원서
- Python
- 해시
- SQL
- 티스토리챌린지
- 소프티어
- java.lang 패키지
- Spring
- Computer Science
- 프로그래머스
- Steve Jobs
- 백준
- nextInt
- Java
- 오블완
- thinking differently
- programmers
- 알고리즘
- 관계형 데이터베이스
- Java script
- 반복문
- JavaScript
- StringTokenizer
- Today
- Total
도라에몽 개발자
클래스(Class); 프로토타입(Prototype) 본문
프로토타입(Prototype) vs 클래스(Class)
"JavaScript는 프로토타입 기반의 언어(prototype-based language)이다."
■ JavaScript 또한 객체지향 언어이나 Java와 같은 객체지향 언어와는 달리, 클래스(Class) 대신 프로토타입(Prototype)이 존재함.
■ 모든 객체들이 메소드와 속성들을 상속 받기 위한 템플릿으로써 프로토타입 객체(prototype object)를 가진다는 의미임.
■ 함수(Function)로 객체(Object)를 생성하여 클래스(Class)처럼 사용하게 됨.
*** 함수로 객체를 생성하여 해당 함수 내에서 생성자(constructor)를 선언한 후, new 키워드를 사용하여 해당 함수에 대한 프로토타입 객체 생성 및 연결 가능함.
class A { // 클래스(class) A 선언
constructor() {} // 생성자(constructor) 구문
}
▼ 클래스(class) 개념이 없기 때문에 상속 기능 또한 없으나, 프로토타입을 기반으로 상속 기능을 구현하여 사용함을 참고할 것.
→ extends 키워드 사용하여 클래스 간의 상속 관계 만들어줌.
// 상속(inheritance)
class A {
constructor() {}
}
class B extends A { // A 클래스 - 부모, B 클래스 - 자식
constructor() {
super()
}
}
class C extends B { // B 클래스 - 부모, C 클래스 - 자식
constructor() {
super()
}
}
prototype
Array
- 정의
- 다른 프로그래밍 언어의 배열과 마찬가지로, Array 객체는 여러 항목의 컬렉션을 단일 변수 이름 아래 저장할 수 있고 일반적인 배열 연산을 수행하기 위한 멤버가 있음.
- prototype 속성에 연결된 메서드를 주로 활용함.
[참고]
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array
Array - JavaScript | MDN
다른 프로그래밍 언어의 배열과 마찬가지로, Array 객체는 여러 항목의 컬렉션을 단일 변수 이름 아래 저장할 수 있고, 일반적인 배열 연산을 수행하기 위한 멤버가 있습니다.
developer.mozilla.org
- Array 인스턴스의 prototype 속성의 메서드 종류
Array.prototype.___
- length() 메서드: 배열의 길이 반환함.
- includes() 메서드: 배열의 항목에 특정 값이 포함되어 있는지 판단하고, true/false 반환함.
...
▼ Array 인스턴스 및 prototype 속성인 length() 및 includes() 메서드 활용 예시
// 생성자 함수 new Array 로부터 할당된 인스턴스(instance) fruits는 다음과 같음.
const fruits = new Array('Apple', 'Banana', 'Cherry')
console.log(fruits) // ['Apple', 'Banana', 'Cherry']
console.log(fruits.length) // 3
console.log(fruits.includes('Banana')) // true
console.log(fruits.includes('Strawberry')) // false
Array.prototype.JJack = function () { // 인위적으로 JJack이라는 이름의 메서드 생성
console.log(this)
}
fruits.JJack() // ['Apple', 'Banana', 'Cherry']
const arr = [] // 새로운 배열 arr 생성
arr.JJack()
▼ 다른 함수에서 선언한 메서드를 빌려서, 원하는 결과를 출력하는데 사용한 예시
// jjack 함수 생성
const jjack = {
firstName: 'JJack',
lastName: 'Sparrow',
getFullName() {
return `${this.firstName} ${this.lastName}`
}
}
// mark 함수 생성
const mark = {
firstName: 'Mark',
lastName: 'Lee',
// getFullName() {
// return `${this.firstName} ${this.lastName}`
// }
}
console.log(jjack.getFullName())
/* mark 함수에서 중복의 getFullName 메서드를 선언하지 않고,
jjack 함수의 getFullName 메서드를 빌려서 원하는 결과를 출력하는 방법은 다음과 같음. */
console.log(jjack.getFullName.call(mark))
▼ 위의 예시와는 달리, prototype 속성의 메서드를 선언하는 방법을 통해 공통으로 사용되는 메서드를 만들어 공유하는 방법의 예시
function User(first, last) {
this.firstName = first
this.lastName = last
}
// prototype 속성 활용하여 공통적으로 사용할 getFullName과 같은 메서드 정의함.
User.prototype.getFullName = function () {
return `${this.firstName} ${this.lastName}`
}
// new User: 생성자 함수
const jjack = new User('JJack', 'Sparrow') // JJack, Sparrow 인자를 가진 새로운 객체(jjack) 생성
const mark = new User('Mark', 'Lee') // Mark, Lee 인자를 가진 새로운 객체(mark) 생성
console.log(jjack) // User {firstName: 'JJack', lastName: 'Sparrow'}
console.log(mark) // User {firstName: 'Mark', lastName: 'Lee'}
console.log(jjack.getFullName()) // JJack Sparrow
console.log(mark.getFullName()) // Mark Lee
ES6 Class 기본 문법
2015년에 발표된 JavaScript의 새로운 문법
// function User(first, last) {
// this.firstName = first
// this.lastName = last
// }
// User.prototype.getFullName = function () {
// return `${this.firstName} ${this.lastName}`
// }
/* 위와 같은 내용을 클래스 형식으로 변환한 결과는 다음과 같음.
User 클래스 내에서 first, last 인자를 포함한 생성자와 getFullName 메서드 생성함. */
class User {
constructor (first, last) {
this.firstName = first
this.lastName = last
}
getFullName() {
return `${this.firstName} ${this.lastName}`
}
}
const jjack = new User('JJAck', 'Sparrow')
const mark = new User('Mark', 'Lee')
// 객체 데이터가 생성되어 다음과 같은 결과가 출력됨.
console.log(jjack) // User {firstName: 'JJAck', lastName: 'Sparrow'}
console.log(mark) // User {firstName: 'Mark', lastName: 'Lee'}
Getter, Setter
- Getter
- 값을 얻어내는(조회하기 위한) 용도의 메서드
- get 메서드명() { ... 리턴문 } - Setter
- 값을 지정하는 용도의 메서드
- set 메서드명(변수명) { ... }
// User 클래스
class User {
constructor(first, last) {
this.firstName = first
this.lastName = last
}
// getter: 값을 얻어내는 용도의 메서드
get fullName() {
console.log('Getting full name!')
return `${this.firstName} ${this.lastName}`
}
// setter: 값을 지정하는 용도의 메서드
set fullName(value) {
console.log(value)
;[this.firstName, this.lastName] = value.split(' ') // value.split(' '): 띄어쓰기를 기준으로 구분하여 배열 데이터에 저장해줌.
}
}
// User 함수를 new 키워드로 호출하는 것을 생성자 함수라고 함.
// 생성자 함수로 JJack, Sparrow 인자를 포함시켜 jjack 변수에 할당함.
const jjack = new User('JJack', 'Sparrow')
console.log(jjack.fullName)
jjack.firstName = 'Mark'
console.log(jjack.fullName) // firstName 값은 변하여 출력되나, fullName은 변하지 않은 상태로 출력됨.
// 할당 연산자를 사용하여 값을 지정하기 때문에 Setter 실행됨.
jjack.fullName = 'Mark Lee' // value라는 매개변수가 데이터를 받아서 fullName의 값으로 할당함.
console.log(jjack) // User {firstName: 'Mark', lastName: 'Lee'}
정적 메소드(Static methods)
- prototype 메소드
- Array.prototype.메소드명()
- 배열 데이터와 관련된 속성을 가진 메소드 - 정적 메소드
- Array.isArray()
- 인자가 Array (배열)인지 여부를 판별함.
- 출력 결과가 true / false 로 출력됨.
Array.isArray([1, 2, 3]); // true
Array.isArray({ foo: 123 }); // false (배열이 아닌, 객체이기 때문)
Array.isArray("foobar"); // false (배열이 아닌, 문자열이기 때문)
Array.isArray(undefined); // false (배열이 아닌, undefined 이기 때문)
class User {
constructor(first, last) {
this.firstName = first
this.lastName = last
}
getFullName() {
return `${this.firstName} ${this.lastName}`
}
// 정적 메소드 isUser 생성 -> 인스턴스가 아닌, 클래스로 직접 접근하여 사용해야 함.
static isUser(user) {
if (user.firstName && user.lastName) {
return true
}
return false
}
}
const jjack = new User('JJack', 'Sparrow')
const mark = new User('Mark', 'Lee')
const taemin = {
name: 'Taemin Lee',
age: 30
}
console.log(jjack.getFullName()) // JJack Sparrow
console.log(mark.getFullName()) // Mark Lee
// console.log(User.getFullName()) // User 클래스에서 메소드를 바로 호출할 수 없고, 인스턴스(jjack, mark) 통해 호출해야 함.
console.log(User.isUser(jjack)) // true
console.log(User.isUser(taemin)) // false
상속(inheritance) & instanceof
상속(inheritance)
- 상속받는 클래스명 extends 상속해주는 클래스명
- 상속을 해주는 클래스의 내용을 상속 받는 클래스가 상속 받아 사용할 수 있음.
instanceof
- 상속받았는지 확인하고자 하는 클래스명 instanceof 상속해준 클래스인지 확인하고자 하는 클래스명
- 상속 여부 확인함.
class Vehicle {
constructor(acceleration = 1) {
this.speed = 0
this.acceleration = acceleration
}
accelerate() {
this.speed += this.acceleration
}
decelerate() {
if (this.speed <= 0) {
console.log('정지!')
return
}
this.speed -= this.acceleration
}
}
class Bicycle extends Vehicle { // Bicycle 클래스는 Vehicle 클래스 내용을 상속 받아서 사용함.
constructor (price = 100, acceleration) {
super(acceleration) // super 함수를 통해 상속 받은 내용: Vehicle의 acceleration
this.price = price
this.wheel = 2
}
}
const bicycle = new Bicycle(300)
bicycle.accelerate()
bicycle.accelerate()
console.log(bicycle)
console.log(bicycle instanceof Bicycle)
console.log(bicycle instanceof Vehicle)
class Car extends Bicycle {
constructor(liscense, price, acceleration) {
super(price, acceleration)
this.liscense = liscense
this.wheel = 4
}
// Overriding (오버라이딩)
accelerate() {
if (!this.liscense) {
console.error('무면허!') // error 표시로 출력
return
}
this.speed += this.acceleration
console.log('가속!', this.speed)
}
}
const carA = new Car(true, 7000, 10)
const carB = new Car(false, 4000, 6)
carA.accelerate()
carA.accelerate()
carB.accelerate()
console.log(carA instanceof Bicycle)
console.log(carB instanceof Vehicle)
class Boat extends Vehicle {
constructor(price, acceleration) {
super(acceleration)
this.price = price
this.motor = 1
}
}
// instanceof 활용하여 상속 여부 확인 (true/false)
const boat = new Boat(10000, 5)
console.log(boat instanceof Bicycle) // false
console.log(boat instanceof Car) // false
console.log(boat instanceof Vehicle) // true
instanceof & constructor (생성자) 활용 방법
class A {
constructor() {}
}
class B extends A { // B 클래스는 A 클래스로부터 상속 받음.
constructor() {
super()
}
}
class C extends B { // C 클래스는 B 클래스로부터 상속 받음.
constructor() {
super()
}
}
// 인스턴스(instance) a, b, c 생성 (cf. 생성자 함수 A, B, C)
const a = new A()
const b = new B()
const c = new C()
// A 클래스는 B, C 클래스의 부모 클래스이고, B 클래스는 C 클래스의 부모 클래스임.
console.log(c instanceof A) // 인스턴스 c는 A 클래스로부터 상속 받았는지 확인 (true)
console.log(c instanceof B) // 인스턴스 c는 B 클래스로부터 상속 받았는지 확인 (true)
console.log(c instanceof C) // 인스턴스 c는 C 클래스로부터 상속 받았는지 확인 (true)
console.log(c.constructor === A) // 인스턴스 c의 생성자가 A 클래스와 생성자와 동일한지 확인 (false)
console.log(c.constructor === B) // 인스턴스 c의 생성자가 B 클래스의 생성자와 동일한지 확인 (false)
console.log(c.constructor === C) // 인스턴스 c의 생성자가 C 클래스의 생성자와 동일한지 확인 (true)
const fruits = ['Apple', 'Banana'] // Array (배열)
// const fruits = new Array('Apple', 'Banana') // 위와 동일한 결과를 가져옴.
console.log(fruits.constructor === Array) // true
console.log(fruits instanceof Array) // true
'LANGUAGE > JavaScript' 카테고리의 다른 글
표준 내장 객체 (1) | 2023.12.29 |
---|---|
함수 (1) | 2023.12.23 |
연산자와 구문 (1) | 2023.12.22 |
Node.js 설치 시 참고사항 (0) | 2023.12.21 |
JS 데이터 (1) | 2023.12.21 |