배열 고차함수 sort()
- 원본을 손상시키므로 복사 후 정렬
- 정렬 기준이 없으면 아스키코드를 기준으로 정렬
- 정렬 기준으로 콜백 함수 사용하므로 고차함수
// 배열 데이터 정렬하기
const nums = [6, 11, 3, 7, 9, 10, 27, 2, 100, 4, 1];
console.log(nums);
nums.sort();
console.log(nums); // [ 1, 10, 100, 11, 2, 27, 3, 4, 6, 7, 9]
** 위의 코드는 10 을 문자로 보고 1 10 2 순서로 본 것
숫자 오름차순 정렬
- 두 숫자를 비교해서 음수가 나오면 a < b 이므로 자리 유지
- 두 숫자를 비교해서 양수가 나오면 a > b 이므로 자리 변경
// 숫자 오름차순 정렬
nums.sort((a, b) => a - b);
// 숫자 내림차순 정렬
// nums.reverse(); --> sort로 정렬 후 reverse()도 내림차 정렬되긴 함
nums.sort((a, b) => b - a);
객체 정렬
- 객체를 매개변수로 받고 객체의 키를 지정해 기준으로 정렬
// 객체의 나이 기준 오름차순 정렬
userList.sort((a, b) => a.age - b.age );
console.log(userList);
// 급여 내림차
userList.sort((a, b) => b.salary - a.salary);
Javascript 구조 분해 할당(destructuring)
- 객체나 배열을 다시 기본 데이터로 해체하는 것을 의미
- 할당하고자 하는 변수의 개수가 분해하고자 하는 배열의 길이보다 크더라도 에러 발생X
할당할 값이 없으면 undefined로 취급하기 때문 - 분해 대상은 수정 또는 파괴되지 않음
const [가져올 데이터] = [원본 배열, 객체];
const userNames = ['김철수', '강감찬', '박영희'];
// userNames에서 각각의 요소들을 다시 변수에 집어넣고 싶다.
// const kim = userNames[0];
// const kang = userNames[1];
// const park = userNames[2];
const [kim, kang, park] = userNames; // 0번인덱스 꺼내서 kim, 1번 kang...
console.log(`a: ${kim}, b: ${kang}, c: ${park}`)
기본값 default value
- =을 이용하면 할당할 값이 없을 때 기본으로 할당해 줄 값인 '기본값(default value)'을 설정 가능
- 값이 제공되지 않았을 때만 함수가 호출되므로, prompt는 한 번만 호출
// name의 prompt만 실행됨
let [surname = prompt('성을 입력하세요.'), name = prompt('이름을 입력하세요.')] = ["김"];
alert(surname); // 김 (배열에서 받아온 값)
alert(name); // prompt에서 받아온 값
디스트럭쳐링을 통한 변수 교환
- 기존에 임시 변수(ex.tmp)를 활용해서 swap 했는데 디스트럭쳐링을 사용하면 더욱 간단하게 swap 가능
let first = 10, second = 20;
[first, second] = [second, first];
// [first, second] = [20, 10];
console.log((`first : ${first} second: ${second}`));
- 배열에서 몇 개 요소만 기본 타입 변수에 저장하고 나머지들은 따로 하나의 배열에 담아둘 때 스프레드를 사용
- rest는 나머지 배열 요소들이 저장된 새로운 배열
- rest 대신에 다른 이름을 사용해도 되는데, 변수 앞의 점 세 개(...)와 변수가 가장 마지막에 위치해야 함
let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert(name1); // Julius
alert(name2); // Caesar
// `rest`는 배열입니다.
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2
스프레드를 통한 배열 간편 복사
const 복사본 = [...원본배열];
// 스프레드를 통한 배열 간편 복사
const foods = ['감튀', '햄버거', '콜라'];
// const copyFoods = foods.slice();
// const copyFoods = foods.map(f => f);
const copyFoods = [...foods];
foods[0] = '치킨너겟';
copyFoods.push('밀크쉐이크');
console.log('foods: ', foods);
console.log('copyFoods: ', copyFoods);
함수 매개변수 디스트럭쳐링
const { empName, hireDate } = employee;
console.log(`name: ${empName}, hire: ${hireDate}`);
function foo({empName, age}) {
// const {empName, age} = employee;
console.log(`내 이름은 ${empName}입니다.`);
console.log(`나이는 ${age}입니다.`);
}
스프레드로 나머지 요소 가져오기
- 나머지 요소는 새로운 배열로 묶임
// 배열 안에서 맨 앞에 2개만 각각의 변수에 저장하고
// 나머지는 다시 배열로 묶고 싶다.
const numbers = [1, 3, 5, 7, 9, 11, 13];
// const numsCopy = numbers.slice();
// const one = numbers.shift();
// const three = numbers.shift();
const [one, three, ...numsCopy] = numbers;
console.log(one);
console.log(`three: ${three}`);
console.log(`numbers: ${numsCopy}`);
프로퍼티 키와 다른 이름을 가진 변수
분해하려는 객체의 프로퍼티: 목표 변수
const { age:empAge, birthDate } = employee;
console.log(empAge);
- 변수명으로 사용할 수 없는 프로퍼티 키를 변수에 저장할 때도 사용
// 변수명에 '-' 사용 불가
// const {"font-size", background-color} = divStyle;
const {"font-size": fontSize, 'background-color': bgColor} = divStyle;
console.log(fontSize);
console.log(bgColor);
객체 디스트럭쳐링 ***
const {var1, var2} = {var1:..., var2:...}
{ 객체 프로퍼티의 패턴 } = { 분해하려는 객체 }
// age만 수정, favorite 추가하면서 복사
const copyDog2 = {
...dog,
age: 20,
favorite: ['산책']
};
// 출력
{
kind: '말티즈',
name: '해피',
age: 20,
injection: false,
favorite: [ '산책' ]
}
나머지 패턴 ‘…’
- 분해하려는 객체의 프로퍼티 개수가 할당하려는 변수의 개수보다 많다면 나머지 패턴(rest pattern)을 사용
const{ kind, age: petAge, ... rest } = dog;
스프레드로 객체 복사
// 객체 안전 복사
const copyDog = { ... dog };
copyDog.age = 10;
console.log(dog);
console.log(copyDog);
Javascript 클로저
- 클로저(closure)란 외부 변수를 기억하고 이 외부 변수에 접근할 수 있는 함수
- 클로저를 통해 지역변수의 스코프를 늘려줄 수 있음
클로저가 필요한 이유
- 아래 코드를 보면 num을 전역변수로 두고 num의 값을 1씩 증가시키는 함수 increase를 선언했을 때 중간에 어떤 코드가 num의 값을 수정하면 결과가 변함
- 이런 이유 때문에 전역변수 사용을 자제해야 함
→ 어떻게 num을 지역변수처럼 함수 내부에서만 사용할까?
// 카운팅 변수
let num = 0; // 전역 변수
// 카운트 숫자 상태 변경 함수
const increase = () => ++num;
console.log(increase());
num = 999;
console.log(increase()); // 2? => 1000
** 클로저 적용한 코드
- 어떤 함수가 내부에 있는 헬퍼 함수를 리턴하게 하는 방법으로 클로저를 구현
- num변수는 함수 외부에서 접근할 수는 없지만 지속적으로 값이 increase에 의해 제어되는 형태로 상태값이 유지되는 효과를 얻을 수 있음
const increaseClosure = () => {
let num = 0; // 상태변수 (지역변수)
function increase() {
return ++num;
}
return increase;
};
const increase = increaseClosure();
console.log(increase());
console.log(increase());
console.log(increase()); // 3? OK!!
즉시 실행 함수
- 함수를 1회성으로 사용할 목적으로 만드는 함수로 익명함수
- 이름이 없어서 다른 곳에서 호출 불가
(function() {
console.log('hello');
})();
const increase = (() => {
let num = 0;
return () => ++num;
})();
console.log(increase());
console.log(increase());
console.log(increase());
** operate, operateSol, operateSol2
세 함수 모두 동일하게 작동하며 표현만 다름
const operate = () => (n1, n2) => n1 * n2; // 실무에서 이렇게까지 줄이지는 않음
const operateSol = () => {
return (n1, n2) => n1 * n2;
};
const operateSol2 = () => {
return function(n1, n2) {
return n1 * n2;
};
};
클로저로 여러 함수를 가진 객체 리턴
- 하나의 변수를 유지하면서 여러 연산 (더하기, 빼기, 결과 반환)을 적용해야 하는 경우
하나의 객체 안에 여러 헬퍼 함수를 담아서 리턴
function createCalculator() {
let total = 0; --> 마치 전역변수처럼 여러 함수를 사용해도 유지
return {
add: num => total += num,
subtract: num => total -= num,
getTotal: () => total
};
}
*** 클로저 는 이외에도 더 많은 내용이 있으니 참고
Web API DOM
DOM (Document Object Model)
- HTML문서를 파싱하여 브라우저가 이해할 수 있는 자료구조인 DOM을 생성
- DOM이란 HTML문서의 계층적 구조와 정보를 표현하며 이를 제어할 수 있는 API를 제공하는 트리 형태의 자료구조
=> HTML 태그들을 객체화
// HTML 구조
<div class="wrap clearfix" title="abc">
<ul id='list'>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
// div 객체화
div = {
tagName: 'div',
children: [ul],
parentNode: body,
nextSibling: null,
prevSibling: null,
className: 'wrap clearfix',
classList: ['wrap', 'clearfix'],
attributes: {
'class': 'wrap clearfix',
'title': 'abc'
}
}
console.log(div.parentNode.parentNode);
// { tagName: 'html', children: [ undefined, undefined ] }
HTML 요소와 노드 객체
- 태그 요소는 요소 노드 객체로 변환
- 요소의 속성은 어트리뷰트 노드로, 텍스트 콘텐츠는 텍스트 노드로 변환
- 이런 노드 객체들을 트리화한 구조로 구성
1. 문서 노드(document node)
- DOM트리의 최상위에 존재하는 루트 노드이며 document객체
- 다른 노드들에게 접근하기 위한 진입점 역할
2. 요소 노드(element node)
- 각 html요소들을 가리키는 객체
- 중첩된 태그에 의해 부모 자식 상속관계를 형성합니다.
3. 어트리뷰트 노드(attribute node)
- 속성에 대한 데이터를 모아놓은 객체이며 해당 요소 노드와 형제 관계\
4. 텍스트 노드(text node)
- 텍스트 노드는 요소 노드의 자식 노드
요소 노드 접근 방법
1. id를 통한 접근
document.getElementById('아이디')
2. css 선택자를 통한 접근 (요소 1개)
document.querySelector('css선택자')
- 인수로 전달한 CSS선택자를 만족하는 요소 노드가 여러 개인 경우 첫 번째 노드만 반환
- 요소 노드가 존재하지 않으면 null을 반환
- 선택자 문법이 맞지 않으면 DOMException 에러 발생
3. css 선택자를 통한 접근 (해당 요소 모두)
document.querySelectorAll('css선택자')
- DOM 컬렉션 객체인 NodeList라는 유사 배열 객체를 반환
*** getElementById 가 querySelector 보다 빨라서 id가 있으면 getElementById 로 잡는 것이 좋음
유사배열
- 배열전용 push, pop, shift, unshift, filter, map 사용 불가
- 유사 배열 → 배열 변경 방법 : [...유사배열]
const $fItemList = document.querySelectorAll(".f-item"); // NodeList
const $fItemList = [...document.querySelectorAll(".f-item")]; // Array
++ 개인
자바스크립트 컴파일러 바벨
- 바벨은 주로 ES6+ 코드를 이전 버전과 호환되는 코드로 변환하는 데 사용
- 브라우저 호환성에 대한 걱정 없이 최신 자바스크립트 문법을 사용 가능
- 다만 웹팩(Webpack)과 같은 모듈 번들러가 하는 일을 처리하지 못함
출처 https://fe-developers.kakaoent.com/2022/220217-learn-babel-terser-swc/