getElementById("title")
<body>
<h1 class="hello" id="title">Grab me!</h1>
</body>
이면
const title = document.getElementById("title");
console.log(title.innerText); // Grab me!
querySelector(".hello h1")
<body>
<h1 class="hello" id="title">Grab me!</h1>
</body>
이면
const title = document.querySelector("h1");
console.log(title.innerHTML); // Grab me!
document.getElementById("title")랑
querySelector(".hello h1")같음!!
getElementsByClassName<body>
<h1 class="hello" >Grab me!</h1>
<h1 class="hello" >Grab me!</h1>
<h1 class="hello" >Grab me!</h1>
<h1 class="hello" >Grab me!</h1>
</body>
const hellos = document.getElementsByClassName("hello");
console.log(hellos); // 콘솔1
console.log(hellos.innerText); // 콘솔2
console.log(hellos[0].innerText); // 콘솔3
결과1

결과2

-> hellos 가 배열(array)라서 불가능
결과3

-> 배열이라 [인덱스값] 형식으로 innerText 가져올 수 있음
getElementsByTagName<body>
<div class="hello">
<h1>Grab me!</h1>
</div>
</body>
이면
const title = document.getElementsByTagName("h1");
console.log(title); // HTMLCollection [h1]
querySelector(".hello h1")<body>
<div class="hello">
<h1>Grab me!</h1>
</div>
</body>
이면
const title = document.querySelector(".hello h1");
console.log(title); // <h1>Grab me!</h1>
<body>
<div class="hello">
<h1>Grab me!</h1>
</div>
</body>
const title = document.querySelector("#hello");
const title = document.getElementById("hello");
두 코드는 같다.
getElementById VS querySelectorgetElementById("title"):
id="title"로 지정된 요소를 선택합니다.id는 고유하므로 하나의 요소만 반환됩니다.const title = document.getElementById("title");
console.log(title.innerText); // Grab me!
querySelector(".hello h1"):
.hello 클래스 안에 있는 h1 태그를 선택합니다.querySelector는 CSS 선택자를 사용하며, 첫 번째로 일치하는 요소 하나를 반환합니다..hello는 클래스 선택자이며, h1은 태그 선택자입니다. 이 조합으로 특정 요소를 선택할 수 있습니다.const title = document.querySelector(".hello h1");
console.log(title.innerHTML); // Grab me!
getElementById는 요소의 id를 기준으로 선택하고, querySelector는 CSS 선택자를 사용하여 보다 유연하게 선택할 수 있습니다.getElementById는 id 하나만 사용하므로 빠르고 간결합니다.querySelector는 class, id, 태그 등 다양한 조합으로 선택할 수 있어 더 유연하지만, 그만큼 약간 더 복잡할 수 있습니다.따라서 두 코드는 선택하려는 대상이 같지만, 선택 방식과 상황에 따라 어떤 메서드를 사용할지 결정하게 됩니다.
css 선택자h1 {
color: blue;
}
<h1>제목 1</h1> <!-- 파란색으로 적용 -->
<h1>제목 2</h1> <!-- 파란색으로 적용 -->
class 속성을 가진 요소를 선택합니다..을 붙입니다..red-text {
color: red;
}
<p class="red-text">이 문장은 빨간색입니다.</p>
<p class="red-text">이 문장도 빨간색입니다.</p>
id 속성을 가진 요소를 선택합니다.id는 고유해야 하므로 한 요소에만 적용됩니다.#을 붙입니다.#main-title {
font-size: 24px;
}
<h1 id="main-title">주제</h1> <!-- 폰트 크기 24px로 적용 -->
div p {
color: green;
}
<div>
<p>이 문장은 초록색입니다.</p>
<span>이 문장은 영향받지 않습니다.</span>
</div>
>를 사용합니다.div > p {
font-weight: bold;
}
<div>
<p>이 문장은 굵게 적용됩니다.</p>
<div>
<p>이 문장은 영향을 받지 않습니다.</p>
</div>
</div>
+를 사용합니다.h1 + p {
color: purple;
}
<h1>제목</h1>
<p>이 문장은 보라색입니다.</p>
<p>이 문장은 영향받지 않습니다.</p>
~를 사용합니다.h1 ~ p {
font-size: 18px;
}
<h1>제목</h1>
<p>이 문장은 18px입니다.</p>
<p>이 문장도 18px입니다.</p>
a[href] {
color: orange;
}
<a href="example.com">링크</a> <!-- 주황색으로 적용 -->
<a>링크 없음</a> <!-- 영향받지 않음 -->
a[href^="https"] {
color: green;
}
<a href="https://example.com">보안 링크</a> <!-- 초록색으로 적용 -->
<a href="http://example.com">비보안 링크</a> <!-- 영향받지 않음 -->
img[src$=".jpg"] {
border: 2px solid black;
}
<img src="image.jpg"> <!-- 테두리 적용 -->
<img src="image.png"> <!-- 영향받지 않음 -->
a[href*="blog"] {
color: pink;
}
<a href="https://myblog.com">블로그 링크</a> <!-- 분홍색으로 적용 -->
<a href="https://example.com">다른 링크</a> <!-- 영향받지 않음 -->
a:hover {
color: red;
}
<a href="#">링크</a> <!-- 마우스 오버 시 빨간색으로 변함 -->
li:first-child {
font-weight: bold;
}
<ul>
<li>첫 번째 항목</li> <!-- 굵게 적용 -->
<li>두 번째 항목</li>
</ul>
li:nth-child(2) {
color: blue;
}
<ul>
<li>첫 번째 항목</li>
<li>두 번째 항목</li> <!-- 파란색으로 적용 -->
</ul>
p::before {
content: "Note: ";
font-weight: bold;
}
<p>이 문장은 메모입니다.</p>
<!-- Note: 이 문장은 메모입니다. -->
p::after {
content: " 끝.";
}
<p>이 문장은</p>
<!-- 이 문장은 끝. -->
h1, h2, h3 {
color: red;
}
<h1>제목 1</h1> <!-- 빨간색 적용 -->
<h2>제목 2</h2> <!-- 빨간색 적용 -->
<h3>제목 3</h3> <!-- 빨간색 적용 -->
input[type="text"] {
background-color: lightgray;
}
<input type="text" /> <!-- 배경 회색 적용 -->
<input type="password" /> <!-- 영향받지 않음 -->
dir 정보 이용하기<body>
<div class="hello">
<h1>Grab me!</h1>
</div>
</body>
이면
const title = document.querySelector(".hello h1");
console.dir(title);
title.style.color = "red";
-> dir를 이용해서 style.color값을 확인하고 바꿔주기
eventListener 추가하기<body>
<div class="hello">
<h1>Grab me!</h1>
</div>
</body>
이면
const title = document.querySelector(".hello h1");
function handleTitleClick(){
console.log("title was Clicked");
}
title.addEventListener("click", handleTitleClick);
결과 
<body>
<div class="hello">
<h1>Grab me!</h1>
</div>
</body>
이면
const title = document.querySelector(".hello h1");
function handleTitleClick(){
title.style.color = "blue";
console.log("Title was Clicked!");
}
title.addEventListener("click", handleTitleClick);
결과

<body>
<div class="hello">
<h1>Grab me!</h1>
</div>
</body>
이면
const title = document.querySelector(".hello h1");
console.dir(title); // dir를 통해서 onmouseenter등을 알아낸다.
function handleTitleClick(){
title.style.color = "blue";
// console.log("Title was Clicked!");
}
function handleMouseEnter(){
title.innerText = "Mouse is here";
}
function handleMouseLeave(){
title.innerText = "Mouse is gone";
}
title.addEventListener("click", handleTitleClick);
title.addEventListener("mouseenter", handleMouseEnter);
title.addEventListener("mouseleave", handleMouseLeave);
title.addEventListener("click", handleTitleClick);
===
title.onclick = handleTitleClick;
const title = document.querySelector(".hello h1");
console.dir(title);
function handleTitleClick(){
title.style.color = "blue";
// console.log("Title was Clicked!");
}
function handleMouseEnter(){
title.innerText = "Mouse is here";
}
function handleMouseLeave(){
title.innerText = "Mouse is gone";
}
// title.addEventListener("click", handleTitleClick);
title.onclick = handleTitleClick;
// title.addEventListener("mouseenter", handleMouseEnter);
title.onmouseenter = handleMouseEnter;
// title.addEventListener("mouseleave", handleMouseLeave);
title.onmouseleave = handleMouseLeave;
function handleWindowResize(){
document.body.style.backgroundColor = "tomato";
}
window.addEventListener("resize", handleWindowResize);
function handleWindowCopy(){
alert("copier!");
}
window.addEventListener("copy", handleWindowCopy);
function handleWindowOffline(){
alert("S!O!S!");
}
window.addEventListener("offline", handleWindowOffline);
function handleWindowOnline(){
alert("ALL GOOD");
}
window.addEventListener("online", handleWindowOnline);
const h1 = document.querySelector(".hello h1");
console.dir(h1);
function handleTitleClick(){
const currentColor = h1.style.color;
if(currentColor === "blue"){
currentColor = "red";
} else {
currentColor = "blue";
}
}
h1.onclick = handleTitleClick;
// Uncaught TypeError: Assignment to constant variable. at HTMLHeadingElement.handleTitleClick (app.js:10:22) handleTitleClick
Error
const 는 변하면 안되는 것!
const h1 = document.querySelector(".hello h1");
console.dir(h1);
function handleTitleClick(){
const currentColor = h1.style.color;
let newColor;
if(h1.style.color === "blue"){
h1.style.color = "red";
} else {
h1.style.color = "blue";
}
}
h1.onclick = handleTitleClick;
const currentColor = h1.style.color; let newColor; 로 수정해주기
const h1 = document.querySelector(".hello h1");
console.dir(h1);
function handleTitleClick(){
const currentColor = h1.style.color;
let newColor;
if(currentColor === "blue"){
newColor = "red";
} else {
newColor = "blue";
}
h1.style.color = newColor; // ** 이거 안해주면 색 안바뀜!! **
}
h1.onclick = handleTitleClick;
if else 구문안에서만 변화된 컬러 newColor가 설정되기 때문에
if else를 통해서 최종으로 확정된 newColor를 외부구문에서도 설정해줘야 실제 색이 설정된다.
type >> 좀 더 활용할 수 있는게 많다.(다양한목적)
type Player = {
nickname: string,
team: Team,
health: Health
}
interface > 오브젝트의 모양을 타입스크립트에게 설명해 주기 위해서만 사용되는 키워드
interface Player {
nickname: string,
team: Team,
health: Health
}
// interface version
interface User {
name: string
}
interface Player extends User {
}
const nico: Player = {
name: "nico"
}
// ----------------------------
// type version
type User = {
name: string
}
type Player = User & {
}
const nico: Player = {
name: "nico"
}
interface > type보다 더 나은 합체능력
interface User {
name: string
}
interface User {
lastName: string
}
interface User {
health: number
}
const nico: User = {
name: "nico",
lastName: "oh",
health: 100
}
type >> Error : Duplicate identifier 'User' : 중복사용❌
type User = {
name: string
}
type User = { // Duplicate identifier 'User'
lastName: string
}
- 추상클래스는 이걸 상속 받는 다른 클래스가 가질 프로퍼티와 메소드를 지정하도록 해줌
- 만약 User 클래스를 상속한다면 sayHi와 fullName을 구현해야하고,
firstName과 lastName을 갖게 될 것이다.- 상속받는 클래스가 어떻게 동작해야할 지 알려주기 위해서 추상클래스 사용
- 추상클래스 사용하는 이유 : 다른 클래스들이 표준화된 모양 & 표준화된 프로퍼트와 메소드를 갖도록 해주는 청사진을 만들기 위해 사용
protected 추상클래스로부터 상속받은 클래스들이 프로퍼티에 접근하도록 해줌private > protected > public
abstract class User {
constructor(
protected firstName : string,
protected lastName : string
) {}
abstract sayHi(name:string):string
abstract fullName():string
}
// 추상클래스는 (아래와 같은)인스턴스 만드는 것을 허용하지 않음
// new User() // Cannot create an instance of an abstract class
class Player extends User {
fullName(){
return `${this.firstName} ${this.lastName}`
}
sayHi(name: string){
return `Hello ${name}. My name is ${this.fullName()}`
}
}
typescript VS javascripttypescript
abstract class User {
constructor(
protected firstName : string,
protected lastName : string
) {}
abstract sayHi(name:string):string
abstract fullName():string
}
javascript
class User {
constructor(firstName, lastName){
this.firstName = firstName,
this.lastName = lastName
}
}
abstract class User {
constructor(
protected firstName : string,
protected lastName : string
) {}
abstract sayHi(name:string):string
abstract fullName():string
}
class Player extends User {
fullName(){
return `${this.firstName} ${this.lastName}`
}
sayHi(name: string){
return `Hello ${name}. My name is ${this.fullName()}`
}
}
// 아래 interface 코드는 `자바스크립트`에서 보여지지 않는다.
interface User {
firstName : string,
lastName : string,
sayHi(name:string):string
fullName():string
}
// implements : extends를 쓸때보다 코드가 더 가벼워진다.
// User interface 추적불가 : 인터페이스는 타입스크립트에서만 존재하고 자바스크립트에는 존재하지 않는다.
// interface를 상속할 때에는 프로퍼티를 `private | protected`으로 만들지 못한다. > public 으로만 가능
// interface : 클래스의 모양을 알려준다는 점에서 유용하다.& 자바스킙트로 컴파일 되지 않는다.
class Player implements User {
constructor(
public firstName : string,
public lastName : string,
){}
fullName(){
return `${this.firstName} ${this.lastName}`
}
sayHi(name: string){
return `Hello ${name}. My name is ${this.fullName()}`
}
}
추상클래스 VS 인터페이스인터페이스 설명
- 인터페이스를 사용해서 클래스의 특정 메소드나 프로퍼티를 상속하도록 강제하는 방법 즉, 인터페이스는 내가 원하는 메소드와 프로퍼티를 클래스가 가지도록 강제 할 수 있게 해준다.
- 인터페이스는 자바스크립트로 컴파일 되지 않는다.
- 추상클래스와 비슷한 보호를 제공하지만, 인터페이스는 자바스크립트 파일에서 보이지 않는다.
추상클래스 설명
- 추상클래스를 쓰면 자바스크립트에서 일반적인 클래스로 바뀐다. 즉, 파일 크기가 좀 더 커지고, 추가 클래스가 만들어진다는 것을 의미한다.
- 만약 추상클래스를 다른 클래스들이 특정 모양을 따르도록 하기 위한 용도로 쓴다면 같은 역할을 하는 인터페이스는 쓰는 것이 더 유용하다!
ex)class Player extends User>(대신)>class Player implements User로 써줘야한다.
: 타입스크립트에게 오브젝트의 모양을 알려줄 때 사용
type Player = {
}
type alias를 만드는 방법
type Player = number
타입을 특정된 값으로 만들어 사용하는 방법
type Player = "1" | "2"
type 기본 사용방법
type PlayerA = { name : string } const playerA : PlayerA = { name: "nico", }
interface PlayerB {
name: string
}
const playerB : PlayerB = {
name: "nico",
}
type 과 interface 둘의 사용 목적과 결과는 동일 but 할 수 있는 것들이 다름
type PlayerA = {
name: string
}
type PlayerAA = PlayerA & {
lastName: string
}
const playerA : PlayerAA = {
name: "nico",
lastName: "oh"
}
interface PlayerB {
name: string
}
interface PlayerBB extends PlayerB {
lastName: string
}
const playerB : PlayerBB = {
name: "nico",
lastName: "oh"
}
type PlayerA = {
name: string
}
type PlayerAA = PlayerA & {
lastName: string
}
type playerAA = { // 이렇게 추가 불가능 : PlayerAA가 이미 정의 되어있어서 중복불가능 X, 아래 const playerA에 health 입력하면 에러남
health: number
}
const playerA : PlayerAA = {
name: "nico",
lastName: "oh",
health: 10 // Object literal may only specify known properties, and 'health' does not exist in type 'PlayerAA'
}
interface PlayerB {
name: string
}
interface PlayerBB extends PlayerB {
lastName: string
}
interface PlayerBB { // 추가해도 문제없음 && `extends`를 생략해도됨(위코드도 동일 적용)
health: number
}
// const playerB : PlayerBB = {
// name: "nico",
// lastName: "oh",
// health: 100
// }
const playerB : PlayerBB = {
name: "nico",
lastName: "oh",
health: 100
}
만약 > 둘다 extends 없앤다면 아래와 같이 사용해도 무방
즉, 같은 PlayerB로 다른 프로퍼티 계속 중복 추가 가능interface PlayerB { name: string } interface PlayerB { lastName: string } interface PlayerB { health: number } const playerB : PlayerB = { name: "nico", lastName: "oh", health: 100 }
type PlayerA = {
firstName: string
}
class User1 implements PlayerA {
constructor (
public firstName: string
) {}
}
interface PlayerB {
firstName: string
}
class User2 implements PlayerB {
constructor (
public firstName: string
) {}
}
interface Animal {
name: string;
}
interface Bear extends Animal {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
interface Animal: Animal이라는 인터페이스를 정의합니다. 이 인터페이스는 하나의 속성 name을 가지고 있으며, 그 타입은 string입니다.interface Bear extends Animal: Bear라는 인터페이스는 Animal 인터페이스를 상속합니다. 즉, Bear는 Animal이 가진 모든 속성을 가집니다. extends 키워드를 사용하여 상속하고, 추가적으로 honey라는 boolean 타입의 속성을 추가했습니다.const bear = getBear(): bear라는 변수를 선언하고, getBear()라는 함수 호출을 통해 bear 객체를 가져옵니다. 이 함수는 Bear 타입의 객체를 반환할 것으로 예상됩니다.bear.name: bear는 Animal을 상속받기 때문에 name 속성을 가지고 있습니다.bear.honey: bear는 Bear에서 추가된 honey 속성도 가지고 있습니다.Bear는 Animal의 모든 속성을 상속받으며, 추가로 honey 속성을 가집니다.type Animal = {
name: string;
}
type Bear = Animal & {
honey: boolean;
}
const bear = getBear();
bear.name;
bear.honey;
type Animal = { name: string }: Animal이라는 타입을 정의합니다. Animal 타입은 name이라는 string 타입의 속성을 가집니다. 여기서는 interface가 아닌 type으로 구조를 정의한 것입니다.type Bear = Animal & { honey: boolean }: Bear라는 타입은 Animal 타입과 결합합니다. 여기서는 & 연산자를 사용하여 교차 타입을 만듭니다. 이 교차 타입은 Animal 타입의 모든 속성에 추가로 honey라는 boolean 속성을 포함합니다.const bear = getBear(): bear 객체를 선언하고, getBear() 함수가 Bear 타입의 객체를 반환할 것으로 예상됩니다.bear.name: bear는 Animal의 속성인 name을 가집니다.bear.honey: bear는 Bear에서 정의한 honey 속성을 가집니다.& 연산자를 사용하여 타입을 확장하는 교차 타입을 구현할 수 있습니다.Bear는 Animal 타입과 honey 속성을 모두 포함하는 구조를 가집니다.interface는 extends를 사용하여 상속을 하고, type은 & (교차 타입)을 사용하여 확장합니다.type은 단순히 객체의 구조뿐만 아니라 유니언, 교차 타입, 튜플 등의 복잡한 타입을 정의하는 데 더 유연합니다. 반면, interface는 주로 객체의 형태를 정의하는 데 집중합니다.interface는 같은 이름으로 여러 번 선언할 수 있으며, 그것들이 자동으로 병합됩니다. 그러나 type은 중복 선언이 불가능합니다.interface와 type은 대부분의 상황에서 서로 교체 가능하지만, 프로젝트의 요구 사항에 따라 적절한 선택을 해야 합니다. 기본적인 객체 구조를 정의하고 상속이 필요한 경우 interface를, 보다 복잡한 타입 구성을 필요로 하는 경우에는 type을 사용하는 것이 일반적입니다.
- 다향성 : 다른 모양의 코드를 가질 수 있게 해 줌 -> 제네릭 사용
- 제네릭 : placeholder 타입을 쓸 수 있도록 해줌
- 때가 되면 타입스크립트가 placeholder 타입을 concrete 타입으로 바꿔줌
- 코드를 예쁘게 해준다.
- 같은 코드를 다른 타입에 대해서 쓸 수 있도록 해준다.
다형성이란 객체 지향 프로그래밍의 중요한 특징 중 하나로, 같은 인터페이스나 상위 클래스에서 파생된 여러 다른 형태의 객체들이 다른 방식으로 동작할 수 있는 능력을 말합니다.
Animal 클래스에서 speak() 메서드를 정의하면, Dog 클래스에서는 멍멍하고, Cat 클래스에서는 야옹하는 식으로 같은 이름의 메서드가 각기 다르게 동작하는 것이 다형성입니다.이 개념은 코드 재사용성을 높이고, 유지보수를 쉽게 하며, 객체지향 프로그래밍의 유연성을 극대화하는 데 사용됩니다.
interface SStorage<T> {
[key:string]: T
}
SStorage<T>는 제네릭 인터페이스입니다. 이 인터페이스는 [key: string] 구문을 통해 동적 키 값 쌍을 표현합니다. 즉, 이 인터페이스를 사용하면 문자열 키에 어떤 타입의 값이든 저장할 수 있는 객체 구조를 정의하게 됩니다.<T>는 제네릭을 나타내며, 이 인터페이스를 사용할 때 타입을 매개변수로 전달할 수 있습니다. 예를 들어, SStorage<string>는 키가 문자열이고, 값도 문자열인 저장소를 의미합니다.class LocalStorage<T> {
private storage: SStorage<T> = {}
set(key: string, value: T) {
this.storage[key] = value;
}
remove(key: string) {
delete this.storage[key];
}
get(key: string): T {
return this.storage[key];
}
clear() {
this.storage = {};
}
}
LocalStorage<T>는 제네릭 클래스입니다. T는 타입을 나타내며, 이 클래스가 어떤 타입의 데이터를 저장할지 정의할 수 있습니다.private storage: SStorage<T>:
storage는 SStorage<T> 타입의 객체로, 초기값은 빈 객체입니다. 제네릭 인터페이스인 SStorage<T>를 통해 이 객체는 키가 문자열이고 값은 T 타입인 데이터를 저장합니다.set(key: string, value: T):
key와 value를 받아서, storage에 저장합니다.stringsStorage.set("hello", "how are you")는 hello라는 키에 "how are you"라는 값을 저장합니다.remove(key: string):
key를 받아서, 해당 키를 가진 데이터를 삭제합니다.get(key: string): T:
key를 받아서 해당 키에 저장된 값을 반환합니다. 반환되는 값의 타입은 T입니다.stringsStorage.get("hello")는 "how are you"를 반환할 것입니다.clear():
const stringsStorage = new LocalStorage<string>();
stringsStorage는 문자열 타입으로 데이터를 저장하는 LocalStorage 인스턴스입니다. 즉, 이 인스턴스에서는 T가 string으로 지정되었기 때문에, 오직 문자열만 저장할 수 있습니다.stringsStorage.get("key");
stringsStorage.set("hello", "how are you");
stringsStorage.get("key"): key라는 키에 해당하는 값을 가져옵니다. 아직 이 키로 저장된 값이 없으므로 undefined를 반환할 것입니다.stringsStorage.set("hello", "how are you"): hello라는 키에 "how are you"라는 값을 저장합니다.const booleansStorage = new LocalStorage<boolean>();
booleansStorage는 불리언 타입으로 데이터를 저장하는 LocalStorage 인스턴스입니다. 여기서 T는 boolean으로 설정되어 있습니다.booleansStorage.get("key");
booleansStorage.set("key", true);
booleansStorage.get("key"): key라는 키에 해당하는 불리언 값을 가져옵니다. 아직 값이 없기 때문에 undefined를 반환할 것입니다.booleansStorage.set("key", true): key라는 키에 true라는 불리언 값을 저장합니다.이 코드에서 다형성이 중요한 이유는 제네릭을 사용함으로써 다양한 타입에 대해 동일한 로직을 사용할 수 있기 때문입니다. 여기서 다형성은 제네릭을 통해 구현되었고, LocalStorage 클래스는 특정 타입(T)을 요구하지만, 그 타입은 사용하는 시점에서 자유롭게 결정할 수 있습니다.
stringsStorage는 string 타입만을 처리하고,booleansStorage는 boolean 타입만을 처리합니다.따라서, 하나의 클래스가 다양한 타입에 대해 동작하는 것이 다형성의 한 예라고 할 수 있습니다.
LocalStorage<T>는 이 다형성을 실현하는 방식 중 하나로, 여러 타입에 대해 동일한 동작을 적용하면서도 타입 안정성을 제공합니다.LocalStorage 클래스가 string이나 boolean 등 다양한 타입에 대해 동일한 메서드를 사용할 수 있게 다형성을 실현하고 있습니다.다형성을 좀 더 쉽게 이해할 수 있는 예시로, 동물(Animal)과 그 하위 클래스(고양이와 개)를 사용하는 간단한 예제를 소개하겠습니다.
// 부모 클래스: Animal
class Animal {
constructor(public name: string) {}
makeSound() {
console.log("동물이 소리를 냅니다.");
}
}
// 자식 클래스: Dog
class Dog extends Animal {
makeSound() {
console.log("멍멍!");
}
}
// 자식 클래스: Cat
class Cat extends Animal {
makeSound() {
console.log("야옹!");
}
}
// Animal 타입의 배열로 여러 동물을 관리할 수 있음
const animals: Animal[] = [new Dog("바둑이"), new Cat("나비")];
// 다형성을 활용하여 같은 메서드를 호출해도 각 객체는 자기만의 방식으로 동작함
animals.forEach((animal) => {
console.log(animal.name);
animal.makeSound(); // 각각의 객체에 맞는 소리를 냄
});
class Animal:
Animal은 기본적인 동물 클래스로, 모든 동물이 가질 name 속성을 포함합니다.makeSound() 메서드는 기본적으로 "동물이 소리를 냅니다."라고 출력합니다. 이 메서드는 하위 클래스에서 재정의할 수 있습니다.class Dog extends Animal:
Dog 클래스는 Animal 클래스를 상속받습니다. makeSound() 메서드를 재정의(오버라이드)하여 "멍멍!" 소리를 내도록 합니다.class Cat extends Animal:
Cat 클래스도 Animal 클래스를 상속받고, makeSound() 메서드를 재정의하여 "야옹!" 소리를 내도록 합니다.다형성의 예시:
const animals: Animal[]은 Animal 클래스 타입의 배열로, 배열 안에 Dog와 Cat 객체를 함께 저장할 수 있습니다.Dog와 Cat)가 자신의 makeSound() 메서드를 실행한다는 점입니다. animals.forEach()를 통해 배열에 있는 각 객체의 makeSound() 메서드를 호출할 때, 각 객체는 자신의 방식으로 소리를 냅니다. Dog 객체는 "멍멍!", Cat 객체는 "야옹!" 소리를 냅니다.바둑이
멍멍!
나비
야옹!
Animal이라는 부모 클래스에서 makeSound() 메서드를 정의했으며, 이를 Dog와 Cat 클래스에서 각자 다르게 재정의했습니다.Animal 배열에 Dog와 Cat 객체를 모두 넣을 수 있습니다. 이때 각 객체는 같은 makeSound() 메서드를 호출하지만, 자신에게 맞는 동작을 수행합니다.이 예제는 다형성을 이해하기 쉽게 도와주는 기본적인 구조를 보여줍니다. Animal이라는 부모 클래스를 기준으로, 고양이와 개 같은 자식 클래스들이 각자 다른 방식으로 행동하지만, 부모 클래스 타입으로 관리할 수 있다는 점이 다형성의 핵심입니다.
{
"include": [ // JVS로 컴파일하고 싶은 디렉토리 추가
"src"
],
"compilerOptions": {
"outDir": "build", // JVS 파일이 생성될 디렉토리 지정
"target": "es6", // 어떤 버전의 JVS로 TS를 컴파일 하고 싶은지 설정
"lib": ["ES6", "DOM"], // 합쳐진 라이브러리의 정의 파일을 특정해주는 역할 // ex) ["ES6", "DOM"] : es6를 지원하는 서버와, dom 즉 브라우저 환경에서 코드를 실행시킬거다 라는뜻
}
}
"lib": ["ES6", "DOM"]
DOM으로 설정함으로써 아래와 같이 사용방법 및 정의를 볼 수 있다.
