클래스 찍어내기.
class Car {
constructor(modelName, modelYear, type, price) {
this.modelName = modelName;
this.modelYear = modelYear;
this.type = type;
this.price = price;
}
makeNoise() {
console.log(this.modelName + " 빵");
}
}
const car1 = new Car("sorento", '10', "e", 1000);
const car2 = new Car("sonata", '20', "g", 1000);
const car3 = new Car("sm5", '30', "d", 1000);
car1.makeNoise();
car2.makeNoise();
car3.makeNoise();
Car 라는 클래스를 만들어보았다. 클래스를 만들 때 필요한 건 컨스트럭터 함수라고 할 수 있겠다. 그리고, 컨스트럭터 함수 안에는 this에 변수로 받아온 인자를 묶어줄 필요가 있다.
// getters와 setters
class rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}
}
// 새 인스턴스 생성
const rectangle1 = new rectangle(10, 20);
const rectangle2 = new rectangle(15, 20);
const rectangle3 = new rectangle(10, 30);
// getters와 setters
class rectangle {
constructor(width, height) {
this._width = width;
this._height = height;
}
get width() {
return this._width;
}
set width(value) {
if (value <= 0) {
console.log("가로 길이는 0보다 커야지");
return;
} else if (typeof value !== 'number') {
console.log("숫자를 입력해주세요");
return;
}
this._width = value;
}
get height() {
return this._height;
}
set height(value) {
if (value <= 0) {
console.log("세로 길이는 0보다 커야지");
return;
} else if (typeof value !== 'number') {
console.log("숫자를 입력해주세요");
return;
}
this._height = value;
}
getArea () {
const a = this._width * this._height
console.log(a)
}
}
// 새 인스턴스 생성
const rectangle1 = new rectangle(10, 20);
rectangle1.getArea()
// const rectangle2 = new rectangle(15, 20);
// const rectangle3 = new rectangle(10, 30);
배운 것 1. 컨스트럭터에서 값을 할당할 때, this. 뒤에 언더바를 꼭 붙여주기.
배운 것 2. 게터스와 세터스를 이용하면 validation에 유용하다는 점.
게터스 세터스라고 하니까 지저스 바제스 형님의 이름이 생각이 나네요 위~하하하하하하하
class Car {
constructor(modelName, modelYear, type, price) {
this._modelName = modelName;
this._modelYear = modelYear;
this._type = type;
this._price = price;
}
get modelName() {
return this._modelName;
}
set modelName(value) {
// 유효성 검사
if (value.length <= 0) {
console.log("모델명이 입력되지 않았습니다.");
return;
} else if (typeof value !== "string") {
console.log("입력된 모델명이 문자형이 아닙니다.");
return;
}
this._modelName = value;
}
get modelYear() {
return this._modelYear;
}
set modelYear(value) {
if (value.length !== 4) {
console.log("모델명이 입력되지 않았습니다. ");
return;
} else if (typeof value !== "string") {
console.log("입력된 모델명이 문자형이 아닙니다.");
return;
}
this._modelYear = value;
}
get type() {
return this._type;
}
set type(value) {
if (value.length <= 0) {
console.log("타입입 입력되지 않았습니다. ");
return;
} else if (value !== 'g' && value !== 'd' && value !== 'e') {
console.log('잘못된 타입입니다.')
}
// 검증 완료
this._type = value;
}
get price() {
return this._price;
}
set price(value) {
if(typeof value !== 'number') {
console.log('숫자를 입력해주세요')
} else if (value <= 100) {
console.log('100만원 이상부터 차로 칩니다. ')
}
// 검증 완료
this._price = value;
}
makeNoise() {
console.log(this.modelName + " 빵");
}
whenManu() {
console.log(this.modelName + "은" + this.modelYear + " 입니다");
}
}
const car1 = new Car("sorento", "10", "e", 1000);
const car2 = new Car("sonata", "20", "g", 1000);
const car3 = new Car("sm5", "30", "d", 1000);
console.log(car1.modelName)
car1.modelName = 1
console.log(car1.modelName)
게터스 세터스를 쓰는 이유는 validation 때문!
이를 활용하기 위한 예제를 한 번 작성해보았다!
상속.
class -> 유산으로 내려주는 주요한 기능들.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} 빽!`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} 멍!`);
}
}
const puppy1 = new Dog("앤디");
puppy1.speak();
애니멀을 부모로 하여 도그라는 클래스를 만들고 스피크를 재정의했다. 이런 재정의를 오버라이드라고 한다.
class Car {
constructor(modelName, modelYear, type, price) {
this.modelName = modelName;
this.modelYear = modelYear;
this.type = type;
this.price = price;
}
makeNoise() {
console.log(this.modelName + " 빵");
}
whenManu() {
console.log(this.modelName + "은" + this.modelYear + " 입니다");
}
}
class ElectronicCar extends Car {
// 재정의가 필요하다면, 컨스트럭터가 필요.
constructor(modelName, modelYear, price, chargeTime) {
// 부모 클래스에도 알려줘야함.
super(modelName, modelYear, "e", price);
this._chargeTime = chargeTime;
}
set chargeTime(value) {
this._chargeTime = value;
}
get chargeTime() {
return this._chargeTime;
}
}
const elecar1 = new ElectronicCar("돌돌이", "2023", "9000", 60);
elecar1.makeNoise();
elecar1.whenManu();
console.log(elecar1._chargeTime);
elecar1.chargeTime = 20;
console.log(elecar1._chargeTime);
자식 요소에 새로운 요소를 추가하거나, 뺄 때는 부모를 명시해줘야함.
부모를 할 때는 super을 쓴다.
// static 메소드 = 정적 메소드.
// Class는 객체를 만들기 위해 ㅏ용.
// 다량으로 안전하고, 정확하게.
class Calculator {
static add(a, b) {
// 그래서 준비했습니다. 스태틱.
console.log("더하기");
return a + b;
}
static subtract(a, b) {
console.log("빼기");
return a - b;
}
}
Calculator.add(3, 5); // 일케 쓰고 시푼데.... 굳이 컨스트럭터 어쩌구저쩌구가 피료했을까?
console.log(Calculator.add(3, 5)); // 이렇게 쓸 수 있다!
클로저
클로저는 함수와 그 함수가 선언덴 렉시컬 환경의 조합.
const x = 1;
function outerFunc() {
const x = 10;
function innerFunc() {
// 함수가 선언된 렉시컬 환경? -> 함수가 선언될 당시의 외부 변수 등의 정보!
console.log(x); // 이너펑크에 없으니 바로 밖의 x를 참조하기에 10.
}
innerFunc();
}
outerFunc();
const x = 1;
// 1
function outer() {
const x = 10;
const inner = function () {
console.log(x);
};
return inner;
}
const innerFunc = outer();
// ----------------- 여기서는 outer 함수의 실행 컨텍스트는...? 사라진다! 그냥 담은 것 뿐이니까.
innerFunc(); // 10.
클로저는 상태를 안전하게 변경하고 유지하기 위해 사용한다.
// 카운트 상태 변경 함수 #3
const increase = (function () {
// 카운트 상태 변수
let num = 0;
// 클로저
return function () {
return ++num;
};
})();
// 이전 상태값을 유지
console.log(increase()); //1
console.log(increase()); //2
console.log(increase()); //3
즉시 실행 함수를 통해 값을 담는 것이 포인트.
숙제에서 고전했던 부분
function makeAnswerCircle(guess) {
const CIRCLE_NAME = "answer";
showCircle(guess, CIRCLE_NAME, $answerCircleArea).then((div) => {
div.id = "answerCircle";
div.append(CIRCLE_NAME);
});
}
function makeGuessCircle(guess) {
const CIRCLE_NAME = "guess";
showCircle(guess, CIRCLE_NAME, $guessCircleArea).then((div) => {
div.id = "guessCircle";
div.append(CIRCLE_NAME);
});
}
function showCircle(size, circleName, area) {
console.log("====================================");
console.log("맨 처음 쇼 서클");
console.log("====================================");
const cx = size + 20;
const cy = size + 20;
const radius = size + 20;
let div = document.createElement("div");
area.appendChild(div);
div.id = `${circleName}`;
div.className = "circle";
div.style.width = 0;
div.style.height = 0;
div.style.left = cx + "px";
div.style.top = cy + "px";
return new Promise((resolve) => {
setTimeout(() => {
div.style.width = radius * 2 + "px";
div.style.height = radius * 2 + "px";
div.addEventListener("transitionend", function handler() {
div.removeEventListener("transitionend", handler);
resolve(div);
});
}, 10);
});
}
마지막에 promise를 반환했으니까, then으로 끌고 갔어야지...
let a = false;
let b = true;
let c = (a || b) && false;
console.log(c);
연산자를 여러 개 계산할 때는 먼저 계산하고 싶은 것부터 괄호를 쳐주자
function sayHello(name = "박민준") {
console.log(`안녕 나는 ${name}이야`);
}
sayHello('dbwl')
이렇게 하면 기본 매개 변수를 세팅 가능하다.
그리고 기본 매개 변수는 맨 끝에서부터 채운다 (중요)
fetch를 통해 TMDB에서 영화를 가져와 카드화하였다.
const main = document.querySelector("main");
const cardWrapper = document.querySelector(".cardWrapper");
const options = {
method: "GET",
headers: {
accept: "application/json",
Authorization:
"Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJlYTNkZjlkMmFlMjRiZGQ5Y2E1Y2YxZWE0YjBlZGZlZSIsIm5iZiI6MTcyODk2NDkzNy4yNDIyMjgsInN1YiI6IjY3MGRlNTdhOWYzNTMxZTZiMjZjNDU5OCIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.npK2DJ6_sFT87OLxSowunNArjpxCtQ-dPQrI9ppT1yE",
},
};
fetch(url, options)
.then((res) => res.json())
.then((data) => {
console.log(data);
for (i = 0; i < data.results.length; i++) {
const temp = `<div class="tempcard">
<img
alt="영화의 이미지가 표현됩니다."
style="width: 200px; height: 300px;"
/>
<ul class="contentWrapper">
<li class="movieTitle">${data.results[i].title}</li>
<li class="movieScore">평점 : ${data.results[i].vote_average}</li>
</ul>
</div>`;
main.innerHTML += temp;
}
})
.catch((err) => console.error("error:" + err));
처음에 조금 헤맸지만, 과거 내가 했던 작품들을 찾아보며 어떻게든 구현해내는데 성공했다.
스타일링도 얼추 됐지만, 문제가 몇 가지 있는데. 일단 검색 기능을 어떻게 구현해야할 지 잘 와닿지 않는다는 점이다.
음... 검색 버튼을 누르면? input된 값을 찾는 로직을 만들어야할 듯 하다.
모달은 display none이나 hidden으로 된 겁나 큰 무언가를 만들고, 그 안에 클릭된(this를 통해서 클릭된 개체를 판단) 카드의 정보를 표시해주는 창구를 만들면 될 듯 하다.