클리닝함수( ['1', 2, '3'] ) 이렇게 숫자와 문자가 섞인 array를 입력하면
[1,2,3] 이렇게 숫자로 깔끔하게 변환되어 나오는 클리닝함수를 만들어오고 타입지정
function 클리닝함수(x: (number | string)[]) {
let 클리닝배열: number[] = [];
if (typeof x === "string") {
클리닝배열.push(parseInt("x"));
} else {
클리닝배열.push(x);
}
}
내가 처음에 만들었던 함수는 이랬다.
근데 클리닝배열 변수를 숫자만 이루어진 배열로 지정해주고,
if문을 이용해 클리닝함수의 요소들을 하나씩 push 해주는 것.
(push : 배열에 요소 추가 / concat : 배열과 배열 합침 - 아니 이걸 누가 아직도 헷갈려서 써여? 나야나)
근데 else { 클리닝배열.push(x); }
에서 x
에 오류가 났다
그러니까 x의 타입은 string 이거나 number
인데 지금 숫자만 들어있는 클리닝배열에 넣을 수 없어! 라는 말이다.
그래서 x의 타입을 assertion 문법으로 덮어씌워주면 되나...? 하고
else { 클리닝배열.push(x as number); }
라고 바꿔봤는데 이번엔 다른 오류가 나왔다.
x를 다짜고짜 숫자로 바꾸려고 한 게 잘못이다.
바보같지만... x는 배열 내 숫자or문자가 아니라 그렇게 이루어진 배열이다..
그러니 number를 넣으면 , 아니 초반에는 숫자/문자로 이루어진 배열이라더니 이걸 어떻게 number로 뒤집어쓰란말임??? 이 되는 것..
그러니 x 배열의 요소 하나하나를 실행할 또다른 메소드가 필요할 것이다.
나는 forEach를 이용해 보았다.
function 클리닝함수(x: (number | string)[]) {
let 클리닝배열: number[] = [];
x.forEach((a) => {
if (typeof a === "string") {
클리닝배열.push(parseInt("a"));
} else {
클리닝배열.push(a);
}
});
}
선생님이 가르치고 있는 여러 과목중 맨 뒤의 1개를 return 해주는 함수
일단 쌤들의 과목도 타입지정을 해줌
let 철수쌤: { subject: string } = { subject: "math" };
let 영희쌤: { subject: string[] } = { subject: ["science", "english"] };
let 민수쌤: { subject: string[] } = { subject: ["science", "art", "korean"] };
그리고 함수를 만들어 보았다.
function 마지막과목(x: { subject: string[] | string }) {
if (Array.isArray(x.subject)) {
return x.subject.pop();
} else {
return x.subject as string;
}
}
많은 이가 알고 있듯 pop() 말고도 마지막 배열 요소를 가져오는 방법은 많다... pop()은 원래 배열을 건드리기 때문에 안 사용하는 것이 좋지만, 여기선 어차피 가져오기만 하면 될 거니깐 나는 pop을 씀
막간 코너~😁
x[x.length - 1]
요소의 제일 마지막 요소를 가지고 옴.x[index숫자~~]
를 넣으면 요소를 출력할 수 있는데, 그 숫자를 x의 길이 -1 을 하면 가장 마지막 요소를 가지고 올 수 있다x.slice(-1)[0]
사용하기. slice()
는 배열의 특정 구간을 자를 때 사용하는 함수다. slice(-1)
은 배열의 마지막 Index에서, 배열의 마지막까지 범위에 해당하는 요소들을 잘라서 배열로 리턴하는 것이기 때문에 [0]
으로 인덱스 지정을 해주어 배열의 마지막 요소만 가지고 올 수 있음.x.at()
으로 배열의 마지막 요소 접근하기. Array.at()
이라는 새로운 함수가 있는데, at(-1)
은 마지막에서 첫번째 요소에 접근하고, at(-2)
는 마지막에서 두번째 요소에 접근한다. 근데 이건 신 문법이라 못 쓰는 곳도 많음. x.pop()
사용. Array.pop()
은 배열에서 마지막 요소를 삭제하고, 그 값을 리턴한다. 그러니까 내가 위에서 이렇게 써버렸으니, 쌤들은 이제... 가르치는 과목을 잃었을 것임. ㅠㅠ 그래서 수정했다..(결론) js로 바꾸는 과정에서 자꾸 배열이 바뀌어 버림..
let 철수쌤: { subject: string } = { subject: "math" };
let 영희쌤: { subject: string[] } = { subject: ["science", "english"] };
let 민수쌤: { subject: string[] } = { subject: ["science", "art", "korean"] };
function 마지막과목(x: { subject: string[] | string }) {
if (Array.isArray(x.subject)) {
return x.subject.slice(-1)[0];
} else {
return x.subject as string;
}
}
타입을 변수로 지정해서 조금 깔끔하게 표현해보기
type SubjectType = { subject: string | string[] };
let 철수쌤: SubjectType = { subject: "math" };
let 영희쌤: SubjectType = { subject: ["science", "english"] };
let 민수쌤: SubjectType = { subject: ["science", "art", "korean"] };;
참고로 타입 변수명은 대문자로 시작하는 것이 국룰
아무튼 단축도 해봤고.. 이제 위에서 만든 함수를 콘솔에 찍어서 확인해 보면...
잘 불러오는 걸 알 수 있다.
근데 타입스크립트 콘솔로 어떻게 불러오냐??? 자바스크립트밖에 인식 못하잖아?
일단 tsc 를 터미널에 입력해서 js 파일로 바꿔준다.
지금 내 typescript 파일이름은 index.ts
임.
tsc index.ts
이렇게 해주면 어쩌고저쩌고 끝에 index.js
가 만들어 진다.
그럼 html 파일하나 만들어서,
<script src="index.js"></script>
넣어주고, 실행시켜주면 됨.
근데 콘솔로그는 잘 찍히는데 또다른 에러가 생겼다.
cannot redeclare block-scoped variable '~'
두 가지 방법이 있는데,
tsconfig.json
파일에 아래 내용을 추가하면 된다.
"compilerOptions": {
"lib" : [ "ES2015"]
},
혹은 빈 object를 export 해주면 된다
export {};
왜 이런 오류가 생기는고하니,
TLDR; TypeScript uses the DOM typings for the global execution environment. In your case there is a 'co' property on the global window object.
To solve this: Rename the variable, or Use TypeScript modules, and add an empty export{}: or Configure your compiler options by not adding DOM typings:
타입스크립트는 전역 환경에서 DOM 타이핑을 사용해서 이미 전역 변수로 선언되어 있을 수 있다.
이럴 때는 변수를 renaming
하거나 export{}
해서 전역 환경과 분리하거나 혹은 컴파일러 옵션을 변경
해 DOM typing을 제거하는 방법으로 해결할 수 있다. (위 json파일 수정)
일단 strictNullCheck
옵션을 준다.
많은 환경에서 null이 들어올 경우 체크해주는 옵션을 켜고 코드를 짜는데, 이유는 변수 조작하기 전에 이게 null인지 아닌지 캐치해낼 수 있기 때문이다.
특히 html 조작할 때 셀렉터로 찾으면 null 어쩌구가 많이 발생하는데 그거 잡을 때도 도움이 된다고.
어떻게 쓰냐면
아까 그 json 파일 컴파일러에 "strictNullChecks": true
를 추가해주면 됨!
버튼을 누르면 이미지를 바꾸는 작업
<img id="image" src="test.jpg">
html 안에 이런 태그가 있다.
이걸 바꾸려면,
let 이미지 = document.querySelector("#image");
이미지.src = "new.jpg";
이렇게 해주면 된다.
근데 이렇게 하면 오류가 뜸. 왜냐면 우리가 위에서 strictNullChecks 옵션을 켜주었기 때문에
이거 Null 일 수도 있어~ 하고 알려준다
따라서 type narrowing을 해줌
let 이미지 = document.querySelector('#image');
if (이미지 instanceof HTMLImageElement){
이미지.src = 'new.jpg';
}
다양한 링크의 주소를 바꾸는 방법
<a class="naver" href="naver.com">링크</a>
<a class="naver" href="naver.com">링크</a>
<a class="naver" href="naver.com">링크</a>
의 주소를 모두 카카오로 바꿔본다.
let 링크 = document.querySelectorAll(".naver");
링크.forEach((a) => {
if (a instanceof HTMLAnchorElement) {
a.href = "https://kakao.com";
}
});
forEach를 사용해서 풀었지만 map을 사용해서도 가능했다.
let 링크 = document.querySelectorAll(".naver");
let 링크배열 = Array.from(링크);
링크배열.map((a) => {
if (a instanceof HTMLAnchorElement) {
a.href = "https://kakao.com";
}
});
Array.from에 대한 정보
반복문을 사용할 경우
let 링크 = document.querySelectorAll(".naver");
for (let i = 0; i < 3; i++) {
let a = 링크[i];
if (a instanceof HTMLAnchorElement) {
a.href = "https://kakao.com";
}
}
for문을 이용할 경우엔 변수를 만들ㄹ어줘야 매끄러운 narrowing이 가능하다.
3번 문제에서 사용한 querySelector
는 , class 모두 접근 가능하다.
하지만 getElementBy~~
는 ~~ 부분에 들어오는 선택자만 접근할 수 있다
즉 getElementById
는 id만 불러올 수 있는 것이다.
위의 4 번문제를 풀었을 때, querySelector
를 이용하면 NodeList
로 출력이 된다.
그래서 여러 개의 요소를 선택하게 되면, index 값으로 접근이 가능하다.
getElementsByClassName
은 HTMLCollection
을 출력한다.
HTMLCollection
은 querySelector
와 다르게 name, id, index번호로 접근 가능하기 때문에 처리속도에서 훨 좋다.
자세한 정보는 여기에 필요한 정보가 잘 담겨있음..
let 이미지 = document.getElementById("#image");
if (이미지 instanceof HTMLImageElement) {
이미지.src = "change.jpg";
}
3번은 간단하게 변경이 되지만 여러개를 불러온 class는 다르다.
let 링크 = document.getElementsByClassName("naver");
링크.forEach((a) => {
if (a instanceof HTMLAnchorElement) {
a.href = "https://kakao.com";
}
});
이렇게 변경하면 오류가 뜸.
위에서 한 말대로 getElementsByClassName
로 가져온 값은 prototype이 HTMLCollection
이다.
그렇기 때문에 forEach는 사용하지 못하고,
위에서 사용한 반복문을 이용해주면 된다.
let 링크 = document.getElementsByClassName("naver");
for (let i = 0; i < 3; i++) {
let a = 링크[i];
if (a instanceof HTMLAnchorElement) {
a.href = "https://kakao.com";
}
}
아니면 HTMLCollection으로 가져온 값을 배열로 바꿔줄 수도 있음.
let 링크 = document.getElementsByClassName("naver");
Array.from(링크).forEach((a) => {
if (a instanceof HTMLAnchorElement) {
a.href = "https://kakao.com";
}
});
Array.from(링크).forEach((a)~~~~~
사용해준 모습..!
Car 클래스를 만들기
{ model : '소나타', price : 3000 }
이렇게 생긴 object를 복사해주는 class를 만들어 본다..tax()
라는 함수를 사용가능한데10분의 1
을 출력class Car {
model;
price;
constructor(a, b) {
this.model = a;
this.price = b;
}
tax() {
return this.price * 0.1;
}
}
let car1 = new Car("소나타", 3000);
이렇게 만들어주고, 이제 타입지정까지 해주면 완료
class Car {
model: string;
price: number;
constructor(a: string, b: number) {
this.model = a;
this.price = b;
}
tax() {
return this.price * 0.1;
}
}
let car1 = new Car("소나타", 3000);
콘솔에 찍어서 확인해주면,
console.log(car1);
console.log(car1.tax());
쉽게 완성시킬 수 있다.
파라미터가 잔뜩 들어가는 class Word
class Word {
num: number[];
str: string[];
constructor(...param) {
let nums: number[] = [];
let strs: string[] = [];
param.forEach((a) => {
if (typeof a === "string") {
strs.push(a);
} else {
nums.push(a);
}
});
this.num = nums;
this.str = strs;
}
}
let obj = new Word("kim", 3, 5, "park");
num
, str
을 콘솔로그에 찍어보면,
아주 잘 출력되고 있음.!
클래스 낯설어.. ㅎ_ㅎ
object 안에 함수를 2개 넣기 (interface 이용)
let 덧셈뺄셈 = {
plus(a,b) {return a+b},
minus(a,b) {return a-b}
}
일단 대충 내부에 들어있는 함수부터 만들어 줌..
그리고 타입지정!
함수 타입 지정은 : () =>
해주면 됨
interface Math {
plus : (a: number,b:number) => number,
minus: (a:number,b:number) => number
}
interface Math {
plus: (a: number, b: number) => number;
minus: (a: number, b: number) => number;
}
let 덧셈뺄셈: Math = {
plus(a, b) {
return a + b;
},
minus(a, b) {
return a - b;
},
};
확인은 덧셈뺄셈.plus(1,3)
등으로 해주면 됨
파트1은 너무 쉬웠고... 그래서 재미있었지만..
(왠지 자바스크립트 처음 배울 때 기분ㅋㅋㅋㅋㅋㅋㅋ )
파트2는 어려울 거 같아서 조금 쫄린다 ㅠ.ㅠ 그래도 얼른 하고 싶어~
파이팅!
초보자 맞춤형인거 같아요 잘보고갑니다!