🦁멋쟁이사자처럼 백엔드 부트캠프 13기 🦁
TIL 회고 - [25]일차
🚀25일차에는 자바스크립트의 함수와 배열 그리고 반복문 등에 대해서 배울 수 있었다.
자바와 유사한 문법이 많았지만 조금씩 다른 점도 보였다.
특히 화살표함수를 활용하여 함수를 정의하고 const 변수에 받는 부분 등이 아직 익숙치 않았지만
자바스크립트의 문법이 조금 유연하다 라는 느낌도 들었다.
또한 함수에 대한 내용이 많아서 회고를 통해 잘 정리되지 않은 내용들을 정리해야겠다고 생각했다.
❓DOM트리
➡️브라우저는 HTML 문서를 읽을 때 각 태그 요소들을 추출해 트리형태로 재조립한다.
이러한 계층적 형태를 DOM 트리라고 부르고 트리라고 부르는 이유는 자료구조의 일종인
"트리 구조"가 계층 관계의 데이터들을 표현하기에 적합하기 때문이다.
즉 HTML 태그들은 상위 태그가 하위 태그를 감싸는 형태로 이루어져 있고, 이러한 종속 관계를 태그로 표현함으로써 트리구조로 표현된 DOM을 DOM트리라고 하는 것이다.
자바스크립트 함수
함수 호이스팅
hello();
// 함수 호이스팅
function hello(){
console.log("Hello");
}
// 중복 가능
function hello(){
console.log("[중복] Hello");
}
- 이렇게 함수가 정의되기 이전에 함수를 호출하는 것을 “함수 호이스팅” 이라고 함
- 만약 중복으로 함수를 정의하면 “가장 마지막에 정의한 함수”가 실행됨
const func1 = function(){
console.log("함수 바로 정의");
}
- 변수에 넣으면서 함수를 함께 선언하는 경우이다.
// const로 정의되었기때문에 "호이스팅 되지 않음"
// var로 정의되었으면 "호이스팅 될 수 있음"
func1();
const func1 = function(){
console.log("테스트코드");
}
- const는 호이스팅 되지 않는다. var로 선언했다면 호이스팅이 될 수 있다.
- 만약 var로 선언하여도 호이스팅은 되지만
➡️“func1 is not defined” ⇒ "정의되지 않음"의 경고문구가 발생된다.
화살표 함수
// 값 두개 받아서 더해서 결과 리턴하는 함수
// 화살표 함수 사용
const add = (a, b) => a + b;
console.log(add(3, 5));
- 화살표함수는 return을 쓰지 않아도 기본으로 “리턴”이 됨
const printName = (name) => console.log("이름 : " + name);
printName("Almiron");
- 출력 : ( 이름 : Almiron )
자바스크립트의 오버로딩
- 자바스크립트는 오버로딩을 지원하지 않는다.
// 자바스크립트는 오버로딩을 지원하지 않음
function add(a) {
console.log("a + a");
return a + a;
}
function add(a, b) {
console.log("a + b");
return a + b;
}
// 자바스크립트는 오버로딩을 지원하지 않기때문에
// 매개변수가 무엇이 들어왔느냐에 상관없이 사용한다.
console.log("[매개변수 1개] : " + add(3));
console.log("[매개변수 2개] : " + add(2, 3));
console.log("[매개변수 3개] : " + add(2, 3, 4));
// arguments 테스트
function argLeng(a) {
console.log(arguments.length + "개");
console.log("[1번째 매개변수 값] : " + arguments[0]);
}
console.log(argLeng(3));
console.log(argLeng(2, 3));
console.log(argLeng(2, 3, 4));
- console.log(arguments) : console.log는 arguments를 받게 되고
- 그 이유로 arguments.length 를 실행해보면 1개, 2개, 3개가 출력되는 것을 확인할 수 있다.
자바스크립트의 객체
const person = {
name : "Barnes",
address : "England"
};
- 객체에 각각 정보를 가지게 만들 수 있는데 이 형태를 “JSON”이라고 함
❓JSON
➡️JavaScript Object Notation의 약어로, 경량의 data 교환 형식을 말한다. name/value (키, 값) 쌍 형태의 값을 가진다.
➡️자바스크립트 뿐만 아니라 많은 언어들이 이러한 데이터 전송 형태를 가지고 있음
💡자바에서는 JSON을 자바객체로 바꿔주는 라이브러리로 “Jackson” 을 사용하기도함, (+Gson)
사용자에게 입력받기
- 브라우저에서는 prompt() 함수를 통해 사용자에게 입력을 받을 수 있지만
- Node.js에서는 prompt() 함수를 사용하지 못한다.
➡️readline 모듈을 사용하여 인터페이스를 정의해주어야한다.
➡️readline 모듈 : Node.js에서 사용자 입력을 받기 위해 사용하는 표준 모듈
createInterface를 통해 입력과 출력을 설정
const readline = require('readline');
// readline 인터페이스 생성
const rl = readline.createInterface({
input: process.stdin, // 입력 스트림
output: process.stdout, // 출력 스트림
});
- readline에 대한 인터페이스를 생성
rl.question("이름을 입력하세요: ", (name) => {
console.log(`안녕하세요, ${name}!`);
rl.close(); // 입력 종료
});
- question() : 사용자로부터 입력을 받는 함수로 "비동기 함수"
➡️비동기 함수 : 입력을 기다리면서 동시에 다음 코드가 실행된다는 것 - 첫 번째 인자로 "질문 문자열", 두 번째 인자로 "입력 값을 처리"하는 콜백 함수 제공
- parseInt() : prompt()는 문자열을 반환하므로, 숫자로 변환해야함
- close() : 입력 처리가 끝난 후 인터페이스를 닫아서 프로세스를 종료시켜야함
- 이렇게 (readline 모듈 사용 + 템플릿 리터럴 + 화살표 함수) 사용한 사용자 입력 처리 코드
객체 비구조화 할당
- 코드를 더욱 짧고 보기 좋게 작성 가능
- “객체 구조 분해” 라고 불리기도 함
▶️실습 - 일반 함수의 객체 출력
const ironMan = {
name: "토니 스타크",
actor: "로버트 다우니 주니어",
alias: "아이언맨",
};
const captainAmerica = {
name: "스티브 로저스",
actor: "크리스 에반스",
alias: "캡틴 아메리카",
};
// 1.0. 일반 함수
function print(hero) {
const text = `${hero.alias}(${hero.name}) 역할을 맡은 배우는 ${hero.actor} 입니다.`;
return text;
}
- 템플릿 리터럴은 백틱( ` ) 으로 감싸주어야한다.
- 위 일반 함수 예제의 경우 text에 템플릿 리터럴을 사용한 문자열을 저장하고 return.
▶️실습 - 객체 비구조화 할당 3가지 방법
// 1.1. 객체 비구조화 할당
function print2(hero) {
const { name, actor, alias } = hero;
return `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`;
}
// 1-2. 객체 비구조화 할당 (일부 요소만 넣어도 가능)
function print3(hero) {
const { name, actor } = hero;
return `${name} 역할을 맡은 배우는 ${actor} 입니다.`;
}
// 1-3. 객체 비구조화 할당 (매개변수로 요소들 직접 넣기)
function print4({ alias, name, actor }) {
return `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`;
}
- 객체 비구조화 할당은 함수 사용을 더 간단히 사용하는 방법.
- hero.alias 처럼 참조해서 불러오던 방식을 직접 alias 로 불러오기가 가능해진다.
- hero 변수에 ironMan이나 captainAmerica 객체를 받아서 사용할 수 있다.
- 1번 방법 : const { name, actor, alias } 처럼 객체가 담긴 hero로부터 비구조화 할당을 해줄 수 있다.
➡️이 경우 객체에서 값들을 추출해서 “새로운 상수”로 선언한 경우이다. - 2번 방법 : {name, actor } 처럼 받아온 hero의 일부요소만 비구조화 할당도 가능
- 3번 방법 : hero를 받아오지 않고 hero의 구조인 alias, name, actor 요소들을 직접 받아오는 방법도 가능
자바스크립트의 this
const dog = {
name: "멍멍이",
sound: "멍멍!!",
say: function () {
console.log("[this.sound] : " + this.sound);
console.log("[객체 안에서의 this] : " + this);
},
};
// 변수 안에 함수도 정의할 수 있다.
dog.say();
- 객체 안에 함수를 정의 ➡️함수 이름이 없어도 된다.
- 이처럼 함수가 객체 안에 들어가게되면 this로 “자신이 속해있는 객체”를 가리킬 수 있음
- 자바스크립트는 자바처럼 클래스를 작성하지 않아도 script만 작성하면 어디에서도 실행이 잘 된다.
➡️이유 : 브라우저에서 전체 script를 감싸고 있는 객체가 Window라는 객체이고
이 Window라는 객체의 구성요소로 "선언하고 만들었던 요소들이 추가되고 있기때문"에 실행이 가능한 것이다.
- console.log(this) : this키워드를 console.log를 통해 확인해보면 Object가 global로 선언되어있다.
- global에서의 this는 전역 객체를 가리키는데 이때 this가
➡️브라우저 환경에서는 Window 객체
➡️Node.js 환경에서는 global 객체인 Object 객체를 참조하는 것이다.
객체 안에서의 함수 차이점
const dog = {
name: "멍멍이",
sound: "멍멍!!",
say: function () {
console.log("[this.sound] : " + this.sound);
console.log("[객체 안에서의 this] : " + this);
},
// 밑처럼 화살표 함수를 사용하지 않아야한다.
say2: () => {
console.log("[화살표함수 this]" + this);
console.log(this.sound);
};
- 객체 안에서 함수 선언 시 화살표 함수로 정의하지 않는 것이 좋다. ➡️ this가 가리키는 부분이 다르기 때문이다.
- 위의 dog객체에서 일반 함수에서의 this와 화살표함수에서의 this를 비교해보면
➡️일반 함수에서의 this는 브라우저에서 Object 객체를 가리키고 “객체 영역”을 포함함 (객체 - Object)
➡️화살표 함수의 this는 브라우저에서 Window 객체를 가리킨다. “전체 영역”을 포함함 (전역 - Windows)
- 브라우저에서 객체 안 함수 1) 일반 함수 say()와 2)화살표함수 say2()를 테스트해보면
➡️일반함수는 object Object 타입이고
➡️화살표함수는 object Window 타입 확인 가능 - 정리하자면 객체 안에서 함수를 정의할때에는 화살표 함수를 사용하면 안된다.
function으로 선언한 일반 함수는 this가 자신이 속한 객체를 가리키지만 화살표 함수는 그렇지 않기때문이다.
Getter Setter
- 자바스크립트에서도 Getter Setter 함수를 통해 값을 넣거나 가져올 수 있다. (get, set 키워드 사용)
const numbers = {
a : 1,
b : 2,
get sum() {
return this.a + this.b;
}
}
numbers.a = 5; // numbers 객체의 a요소 값 수정 = 5
console.log(numbers); // numbers 객체의 출력 결과
console.log(numbers.sum); // numbers 객체의 get 함수 출력 결과
- get 키워드를 통해 함수를 만들면 getter 함수를 의미
get a(){
console.log("[a꺼내기]");
return this.a;
},
console.log(numbers.a); // 1 출력
- get 키워드를 통해 요소 값을 가져올 수 있다.
- return this.a :
➡️ console.log(numbers.a) 를 통해 get a() 함수를 호출하고 이 함수는 this.a를 리턴하지만
⚠️이 과정에서 다시 이름이 같은 get a()함수를 호출하게 되어 무한적으로 재귀호출되는 문제가 발생할 수 있다. - ➡️해결방법 : 내부속성 {a : 1} 을 {_a : 1}로 (언더바 활용) 바꿔주어 재귀호출의 문제를 해결한다.
➡️getter와 setter에서 내부 속성을 참조하고 수정할때
“일반적으로 속성에 _(언더바)로 시작하는 다른 이름으로 바꿔서 재귀 호출 문제를 해결한다.
// 재귀호출 문제 해결한 Getter, Setter
const numbers2 = {
_a: 1,
_b: 2,
get a() {
return "[Getter: a값 꺼내기] : " + this._a;
},
set a(value) {
console.log(`[Setter: a값 재설정] : ${value}`);
this._a = value;
},
get sum() {
return this._a + this._b;
},
};
numbers2.a = 5; // a값 재설정
const output = numbers2.a; // a값 꺼내기
console.log(output);
console.log("[더하기] : " + numbers.sum); // sum()함수를 getter로 불러서 호출하는 경우
자바스크립트 반복문
- 자바와 대부분 유사하다.
- 자바스크립트는 for…of 반복문이 존재하는데 “배열에 관한 반복문” 이다.
➡️주로 배열의 내장 함수를 많이 사용하기때문에 for…of를 사용할 일이 거의 없다.
➡️자바의 forEach문과 유사하다.
▶️실습 - for...of 반복문 사용 (배열에서 활용)
let numbers = [1, 2, 3, 4, 5];
for(let number of numbers){
console.log(number);
}
▶️실습 - for...in 반복문 사용 (객체에서 활용)
- for…in을 사용하고, 키와 값에 대한 출력을 다룬다.
const dog = {
name: "멍멍이",
age: 2,
sound: "멍멍!!",
};
console.log(Object.entries(dog));
console.log(Object.keys(dog));
console.log(Object.values(dog));
- entries()로 전체 값들을 얻어온다.
- keys()로 키 값만 얻어온다.
- values()로 value값만 얻어온다.
for (let key in dog) {
console.log(`${key} : ${dog[key]}`);
}
- dog객체의 [key]로 접근하여 값들을 출력할 수도 있다.
자바스크립트 배열
▶️실습 - 배열 초기화 및 선언
let array1 = [1, 2, 3]; // 대괄호 사용하여 초기화
array1 = [4, 5, 6]; // 값 재설정
const array2 = []; // 빈 배열 선언 (초기화되지 않은 배열)
console.log(typeof array2); // 초기화되지 않은 배열 = object 타입
- 배열의 선언은 여러가지 방법이 있다.
- 첫번째 방법 - [ ] 대괄호 안에 값을 넣어 선언과 동시에 초기화
- 두번째 방법 - 빈 배열을 선언하는 방법
- 세번째 방법 - new키워드를 통해 배열크기를 설정하거나 값을 넣어 선언과 동시에 초기화 하는 방법이다.
▶️실습 - 배열 인덱스 접근
console.log(array1[0]); // 배열 인덱스 접근
array1[2] = 55; // 배열의 2번 인덱스 접근 = 3번째 값
console.log(array1); // 값 재설정한 배열 출력
▶️실습 - 배열 선언 new 활용
const array3 = new Array(10); // 인자로 값이 1개만 들어오면 "배열크기"를 나타냄
const array4 = new Array(10, 2); // [10, 2] 의 값을 가진 배열이 생성됨
console.log(array3);
console.log(array4);
▶️실습 - 배열에 값 넣기
array1[0] = { name: "Isak" }; // array1의 0번째 인덱스를 (키, 값)형태로 넣기
console.log(array1);
array1.push(10); // 배열의 끝에 '10'을 추가
console.log(array1);
array1.push(() => console.log("Function Array!")); // 배열에 함수를 넣을 수도 있음
console.log(array1);
array1[4](); // 배열에 들어있는 함수를 실행할 수 있음
- 배열이 지니고 있는 내장함수 push()함수를 사용
- 배열에는 객체 형태로 값을 넣을 수도 있고, 함수를 넣을 수도 있다.
▶️실습 - 배열의 비구조 할당
// 배열의 비구조 할당
const [a, b, c, d, e] = array1;
console.log(a); // 비구조 할당된 배열 출력하는 방법
▶️실습 - 배열의 값 꺼내기
console.log(array1.pop()); // pop 내장함수 활용
const popFunc = array1[4];
console.log(popFunc);
const popFunc2 = array1[3];
console.log(popFunc2);
- 배열이 지니고 있는 내장함수 pop()함수를 사용
- console.log(popFunc) :
➡️"undefiend" 출력 - pop()함수로 인해 실제 값이 꺼내진 것이기때문에 꺼내진 값은 없어져서 undefined 출력
⚠️pop()함수는 값을 꺼낼 뿐만 아니라 꺼내진 값이 삭제되기때문에 유의
배열의 내장함수들
- stream() 처럼 중요한 함수가 존재한다.
➡️stream() : 자료구조의 데이터들을 “물의 흐름”처럼 펼쳐서 사용할 수 있도록 도와주는 기능
🚀 forEach
// 배열의 내장함수 forEach
const heroes = ["슈퍼맨", "배트맨", "플래시"];
// 1. forEach 사용
const funcHero = function (hero) {
console.log("히어로 : " + hero);
};
heroes.forEach(funcHero);
// 2. forEach (함수 포함) 사용
heroes.forEach(function (hero2) {
console.log("히어로 : " + hero2);
});
// 3. forEach (화살표 함수 포함) 사용
heroes.forEach((hero3) => {
console.log("히어로 : " + hero3);
});
- forEach : 해야할 일을 구현한 함수이다.
- forEach의 매개변수(파라미터) hero는 heroes의 각 원소를 가리키게됨
➡️이처럼 함수 형태의 매개변수(파라미터)를 전달하는 것을 “콜백함수”라 함 - 이렇게 함수를 등록하면 forEach가 등록한 함수를 실행
- 1번방법 : heroes.forEach(hero);
➡️기본적으로는 함수를 파라미터로 넣어주지만
hero함수를 굳이 밖으로 빼낼 필요가 없을때는 forEach 안에서 함수를 정의 - 2번방법 : forEach안에서 일반 함수 정의하는 방법
- 3번방법 : forEach안에서 화살표 함수를 정의하는 방법
map
- 결과값을 만들어서 새로운 배열을 리턴해줌
- map 함수의 파라미터, 즉 map( ? ) 안에는 변화를 주는 함수 (=변화 함수)를 전달해준다.
▶️실습 - map()을 활용하여 기존 배열의 제곱 배열을 구하기
// map : 결과값을 새로운 배열로 만들어 리턴
// 1번방법. 일반적인 제곱 배열 리턴
const values = [1, 3, 5, 7, 11];
const powerValues = [];
for (let value of values) {
powerValues.push(value * value);
}
console.log(powerValues);
// 2번 방법. map() 활용
const powerValues2 = values.map((n) => n * n); // 매개변수 n을 받아서 n * n을 바로 리턴
console.log(powerValues2);
indexOf
- 원하는 값을 넣어서 그 값이 몇번째 원소에 해당되는지 찾아줌
- 만약 배열 안의 값이 “객체이거나 배열”이라면 indexOf로 찾을 수 없다. ➡️해결방법 : findIndex 사용
findIndex
// 0. 샘플데이터
const todoList = [
{
id: 1,
text: "자바스크립트 입문",
done: true,
},
{
id: 2,
text: "반복문 배우기",
done: true,
},
{
id: 3,
text: "함수 배우기",
done: false,
},
];
// 1. findIndex() 사용 - id : 3을 가진 인덱스를 반환
const todoIndex = todoList.findIndex((todo) => todo.id === 3);
console.log(todoIndex);
- 샘플데이터가 담긴 todoList 변수를 findIndex()함수의 파라미터로 "함수 (todo)"를 넣어준다.
- id 값이 3인 인덱스를 가져온다. ➡️0번인덱스 : {id:1}, 1번인덱스 : {id:2}, 2번인덱스 : {id:3}이므로 인덱스 "2" 출력
find
// 2. find() 사용
const todoFind = todoList.find((todo) => todo.id === 2);
console.log(todoFind);
- findIndex() 함수는 인덱스 값만 반환하지만 find() 함수는 객체를 반환할 수 있다.
- id 값이 2인 객체를 가져온다. ➡️{id : 2, text : "함수 배우기", done : false} 객체 출력
filter
// 3. filter() 사용
const todoFilter = todoList.filter((todo) => todo.done === false);
console.log(todoFilter);
- filter() 함수는 특정 조건을 만족하는 객체 값을 가져온다.
- done 키 값이 false인 객체를 가져오게 된다.
splice
// 4. splice() 사용
const todoSplice = todoList.splice(1, 2); // 1번인덱스부터 2개를 잘라냄
console.log(todoSplice); // id:1, id:2, id:3 이기때문에 id:2, id:3이 출력
- 배열을 다룰 수 있지만 splice() 함수를 사용하면 splice()를 통해 수정된 배열로 남게 된다.
- ➡️기존 배열의 구조를 변경하게 된다.
slice
const todoSlice = todoList.slice(1, 2); // 1번인덱스부터 2개를 잘라냄 (기존 배열 유지)
console.log(todoSlice); // id:1, id:2, id:3 이기때문에 id:2, id:3이 출력
- 기존배열을 실제로 잘라내는 splice()함수와 달리 slice()함수는 기존 배열을 유지한다.
❓filter와 splice의 차이점
➡️filter는 조건에 맞는 것만 골라내는 것, splice는 단순히 잘라내는 것
shift
- pop이 마지막 원소를 추출해내는 것과 달리 shift는 첫번째 원소를 배열로부터 추출한다.
unshift
- push가 마지막 부분에 원소를 추가하는 것과 달리 unshift는 처음 부분에 원소를 추가한다.
concat
const arr1 = [1, 2];
const arr2 = [3, 4, 5];
const concated = arr1.concat(arr2);
- 여러 개의 배열을 하나로 합쳐준다.
join
const arr = [1, 2, 3, 4, 5];
console.log(arr.join(', ')); // 1, 2, 3, 4, 5
console.log(arr.join(' | ')); // 1 | 2 | 3 | 4| 5
- 배열 안의 값들을 문자열 형태로 합침
reduce
- 배열의 각 요소를 순회하며 콜백 함수의 실행 값을 누적하여 하나의 결과값을 반환
- 첫번째 파라미터는 누적합을 담을 변수
- 두번째 파라미터는 배열의 다음 요소를 담을 변수
- 더 이상 current의 요소가 없을때 끝내고 반환
// 1-1. reduce 함수
const numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum);
// 1-2. reduce 함수 - 내장함수 출력문 추가
let sum2 = numbers.reduce((acc, curr) => {
console.log(`누적값 : ${acc}, 현재값 : ${curr}`);
return acc + curr;
}, 0);
console.log(sum2);
- 0 : 은 초기값을 의미 → ex. 처음에 이 값이 accumulator 에 들어가고 current은 1일 것
🚀실습 - 마켓 계산시스템 (reduce() 활용)
// reduce 함수 - 응용
const cart = [
{
name: "라면",
price: 800,
},
{
name: "아이스크림",
price: 700,
},
{
name: "음료수",
price: 1500,
},
{
name: "과자",
price: 2000,
},
{
name: "초콜릿",
price: 1000,
},
];
console.log("-----[LEFT Market]-----");
let totalPrice = cart.reduce((acc, curr) => {
console.log(`\\n현재까지 총 가격 : ${acc}원`);
console.log(`계산할 상품[${curr.name}] 가격 : ${curr.price}원`);
return acc + curr.price;
}, 0);
console.log(`\\n계산해주세요!\\n모든 상품의 가격 : ${totalPrice}원`);
🚀 함수에서 활용도가 높은 화살표 함수와 다양한 문법에서 쓰이는 내장함수들을 실습을 통해서 익숙해질 수 있었다.
자바의 문법과 유사한 부분도 많지만 자바스크립트는 새로운 언어를 배우는 느낌이어서
회고를 통해 모르는 부분을 찾아보고 배우는 과정이 뜻깊은 것 같다.
배열의 내장함수 부분은 조금 더 숙련될 필요가 있을 것 같다!
'Recording > 멋쟁이사자처럼 BE 13기' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_27일차_"자바스크립트 이벤트" (0) | 2025.01.09 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_26일차_"자바스크립트 비동기처리" (0) | 2025.01.08 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_24일차_"자바스크립트" (0) | 2025.01.06 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_23일차_"CSS 선택자와 위치 속성" (0) | 2025.01.03 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_22일차_"HTML과 CSS" (3) | 2025.01.02 |