console.log("hey JavaScript"); // hey JavaScript
var name = 'minji';
console.log(name); // minji
// 로그 vs 테이블
console.log({name: "minji", age: 22})
// {name: "minji", age: 22}
console.table({name: "minji", age: 22})
// (index) | Value
// name | "minji"
// age | 22
colsole.error('Error'); // 오류 알림 (빨간색 엑스)
console.warn('warning'); // 워닝 알림 (노란색 느낌표)
console.time('samevalue');
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.timeEnd('samevalue'); // time~timeEnd까지의 소요시간이 출력됨
// samevalue: 0.234242347981ms → 이런 형태!
console.clear(); // 콘솔창 지우기
func(); // 정상적으로 hoisting test가 출력됨
function func() {
console.log('hoisting test');
}
| 변수 선언 방식 | 중복 선언 | 재할당 | 변수의 참조 범위 | 호이스팅 |
|---|---|---|---|---|
var | O | O | 함수 레벨 스코프 | Undefined |
let (ES6) | X | O | 블록 레벨 스코프 | Error |
const (ES6) | X | X | 블록 레벨 스코프 | Error |
var var greeting = 'hello';
console.log(greeting);
var greeting = 'guten morgen'; // 중복선언 O
console.log(greeting);
greeting = 'hola'; // 재할당 O
console.log(greeting);
function func() {
if (true) {
var a = 'a';
console.log(a); // 'a'
}
console.log(a); // 'a'
}
func();
console.log(a); // 함수 외부 호출 - 오류 발생
var는 선언단계에서 Undefined 값이 할당되고 할당단계에서 실제값이 할당되기 때문!console.log(greeting); // Undefined
var greeting = 'hello';
letlet greeting = 'hello';
console.log(greeting);
let greeting = 'guten morgen'; // 중복선언 X: 오류발생
console.log(greeting);
greeting = 'hola'; // 재할당 O
console.log(greeting);
let, const의 경우, 선언 단계에서 Undefined 값이 할당되지 않으므로 var과 달리 오류가 발생함console.log(greeting); // Error: 초기화 전에 접근했으므로 참조오류 발생
let greeting = 'hello'; // const로 변경해도 동일한 결과 발생
const: constant의 약자const greeting = 'hello';
console.log(greeting);
const greeting = 'guten morgen'; // 중복선언 X: 오류발생
console.log(greeting);
greeting = 'hola'; // 재할당 X: 오류발생
console.log(greeting);
{}로 둘러싸인 부분function func() {
if (true) {
const a = 'a'; // let으로 바꿔도 동일한 결과 발생
console.log(a); // 'a'
}
console.log(a); // 불록 외부 호출 - 오류 발생
}
func();
console.log(a); // 불록 외부 호출 - 오류 발생
✨ const가 가장 권장되며, 만약 재할당이 필수적으로 필요한 경우에는 let을 사용함. var의 사용은 지양함.
let foo = 42;
console.log(typeof foo) // number
foo = 'bar';
console.log(typeof foo) // string
foo = true;
console.log(typeof foo) // boolean
타입의 종류:
boolean, string, number, null, undefined, symbolobject, array// Numbers:
let length = 16;
let weight = 7.5;
// Strings:
let color = "Yellow";
let lastName = "Johnson";
// Booleans
let x = true;
let y = false;
// Object:
const person = {firstName:"John", lastName:"Doe"};
// Array object:
const cars = ["Saab", "Volvo", "BMW"];
// Object vs Array: 배열인지 아닌지 확인할 때에는 typeof 사용 X, Array.isArray() 사용
console.log(Array.isArray(cars)); // true
// Date object:
const date = new Date("2022-03-25");
String() ...// Math Object
val = Math.PI // PI
val = Math.round(2.4) // 반올림
val = Math.ceil(2.4) // 올림
val = Math.floor(2.4) // 내림
val = Math.abs(-2) // 절댓값
val = Math.sqrt(64) // 루트
val = Math.min(2, 3, 5, 7, 8, -1) // 가장 가까운 정수 반환
val = Math.max(2, 3, 5, 7, 8, -1) // 가장 가까운 정수 반환
val = Math.random() // 0~1 사이의 랜덤한 수
console.log('첫째줄
둘째줄'); // 줄바꿈이 구현됨
const a = 5;
const b = 10;
// 표현식을 + 기호 없이 포함이 가능해짐
// 기존 방식: "문자열" + (표현식) + "문자열" + ...
console.log(`Fifteen is ${a + b} and not $2 * a + b}.`);
for ([초기문]; [조건문]; [증감문]){
명령문
}
for (let i = 0; i < 10; i++) {
if (i == 3) {
console.log('it is three');
continue;
}
if (i == 5) {
console.log('it is five, stopping the loop');
break;
}
console.log('number: ' + i);
}
// 출력
// number: 0
// number: 1
// number: 2
// it is three
// number: 4
// it is five, stopping the loop
for (variable in object) {
statements
}
const user = { // 객체 정의
name: 'Minji',
province: '경기도',
city: '안양시'
}
for (let x in user) { // key : value
console.log(`${x} : ${user[x]}`);
}
while (조건문){
명령문
}
let i = 0;
while (i < 10) {
console.log('number : ' + i);
i++;
}
do 문장 // 무조건 1회는 실행
while (조건문);
let i = 0;
do {
console.log('number: ' + i);
i++;
}
while (i < 10);
배열을 loop로 컨트롤해주기
const locations = ['germany', 'france', 'spain', 'mexico'];
for (let i = 0; i < locations.length; i++) {
console.log(locations[i]);
}
// 출력결과: 하단의 이미지
locations.forEach(function (location, index, array) {
console.log(`${index} : ${location}`);
console.log(array);
});
locations.map(function (location) {
console.log(location);
});

| for | forEach |
|---|---|
| 기존 방식 | 새로운 방식 |
| break 문 사용 가능 | break 문 사용 불가 |
| await 사용 가능 | await 완벽히 작동 X |
| 속도 상대적으로 빠름 | 속도 상대적으로 느림 |
용도:
1. 브라우저의 창에 대한 정보를 알 수 있고, 창을 제어할 수도 있음
예: window.innerWidth라고 입력하면 창 내부의 너비를 알 수 있으며, 창을 축소하거나 확장함에 따라 해당 수치는 변경됨
↪ 이외에도 window.outerHeight 등이 있음
2. var 키워드로 변수를 선언하거나 함수를 선언하면 window 객체의 property가 됨
var A = 1;
console.log(window.A) // 1
let val;
val = window.scrollY; // 스크롤 했을 때 페이지 상단부터 스크롤한 부분까지의 거리
val = window.scrollX;
console.log(val);
// location object
val = window.location; // location 객체: 아래에서 확인할 수 있듯, host, hostname, port, href, search 등의 정보들을 가지고 있는 객체
val = window.location.hostname;
val = window.location.port;
val = window.location.href;
val = window.location.search;
// redirect
window.location.href = 'http://google.com'; // 페이지를 실행하자마자 해당 링크로 이동시킴
// reload
window.reload();
// history object
window.history.go(-2); // history 객체에는 사용자가 브라우저 창에서 방문한 url이 저장됨
val= window.history.length;
window.history.forward() // 윈도우바 위에 있는 이전으로 가기 화살표와 같은 역할
// navigator object
val = window.navigator;
val = window.navigator.userAgent;
val = window.navigator.language;
console.log(val);
정의: 메모리에 웹페이지 문서구조를 트리구조로 표현한 모델

용도: 웹브라우저가 HTML 페이지를 인식하게 해주고, 자바스크립트가 웹페이지를 이루는 요소들을 이용할 수 있도록 해줌
돔 조작: DOM에서 제공하는 API를 사용해서 DOM 구조에 접근하거나 원하는 요소를 수정/삭제할 수 있음
<button class="button"> Click Mee </button>
// dom 구조 (button이라는 이름을 가진 요소) 에 접근
var button = document.querySelector('.button');
// dom 요소를 수정: 스타일 변경
button.onclick = function () {
this.style.backgroundColor = "red";
}
HTML → DOM ) and ( CSS → CSSOM ) → RenderTree로 결합(DOM (html) + CSSOM (css)) → Layout (✨ 비용이 많이 드는 부분... react에서는 virtual DOM으로 이 부분의 비용을 단축하려고 노력함) → paintDocument Object: window 객체가 브라우저 창이라고 하면, document 객체는 브라우저 내에서 콘텐츠를 보여주는 웹페이지 자체임
css의 프레임워크인 bootstrap을 활용한 예시에 document object를 사용해서 접근 및 수정, 삭제를 시도해봄
요소에 접근하는 방법: getElementById, getElementByName, querySelector
// 파라미터로 전달한 ID를 가진 태그를 반환
document.getElementById(요소아이디);
// 파라미터로 전달한 name 속성을 가진 태그를 반환
document.getElementByName(name속성값);
// 파라미터로 전달한 선택자에 맞는 첫번째 태그를 반환
// 선택자 자리에 class가 오면 #을, id가 오면 .을 붙여서 작성
document.querySelector(선택자);
// 접근
const headContainer = document.getElementById('header-container');
// 스타일링 변경
headContainer.style.fontSize = '10px';
headContainer.style.display = 'none';
// class 이름으로 접근해서 수정해보기
const items = document.getElementsByClassName('list-group-item');
console.log(items);
items[0].style.color = 'blue';
items[3].textContent = 'hey';
// 태그 이름으로 접근해서 수정해보기
let tagItems = document.getElementsByTagName('li');
console.log(tagItems); // collection 상태
// forEach로 순회 시도: 오류
tagItems.forEach((tagItem) => {
console.log(tagItem); // ERROR: forEach is not a function in list !!
})
Array.from(tagItems); // collection -> array로 바뀜
console.log(tagItems); // array 상태
// forEach로 순회 시도: 성공 ~
tagItems.forEach((tagItem, index) => {
// console.log(tagItem);
list.textContent = `${index}. List `;
})
// 그렇다면 <li> 태그 중 홀수번째 태그의 내용들만 선택하려면?
const liOdd = document.querySelectorAll('li: nth-child(odd)');
liOdd.forEach((li) => {
li.style.background = 'pink';
});

document.createElement(태그이름) : 태그이름을 가진 요소를 생성할 수 있음const li = document.createElement('li'); // 요소 생성
li.className = 'list-group-item'; // 클래스명 부여
li.id = 'new-item'; // id 부여
요소.setAttribute : 속성 추가li.setAttribute('name', 'New list item');
const link = document.createElement('a') // a 태그를 가진 요소 생성
document.querySelector'ul.list-group').appendChild(li);
link.className = 'alarm-item';
link.innerHTML = 'hi'; // '<i class="bi-alarm"></i>'
li.appendChild(link);
요소.appendChild() : 요소를 특정 부모 요소의 자식요소 리스트 중 마지막 자식으로 붙임document.querySelector('ul.list-group').appendChild(li);
// 부모요소 불러오기
const listParent = document.querySelector('ul');
// 자식요소들 불러오기
const list = document.querySelectorAll('li');
부모노드.removeChild(자식노드); : 하나의 자식노드 삭제// 0번째 자식요소 삭제
listParent.removeChild(list[0]);
부모노드.replaceChild(새노드, 이전노드); : 이전노드를 삭제하고 새노드로 교체함// 이전노드 (변경해야 할 노드) 선정하기
const oldElement = document.getElementById('A');
// 새 노드 생성하기
const newElement = document.createElement('span');
newElement.textContent = 'hi';
// 요소 교체하기
oldElement.parentNode.replaceChild(newElement, oldElement);
어떤 버튼을 클릭했을 때 지정한 엑션이 발생하도록 하려면 어떻게 해야할까? ✨ 정말 자주 쓰이는 기능... ✨
onclick 메소드 사용
var button =
document.querySelector('.button');
button.onclick = function() {
this.style.backgroundColor = 'red';
};
addEventListener 메소드 사용요소.addEventListener(이벤트명, 실행할 함수명(listener), 옵션);// js
window.onload = function () { // 문서가 로드 될 때 실행
// 아이디가 'text'인 요소 반환
let text = document.getElementById('text');
text.innerHTML = 'HTML 문서 loaded'; // innerText도 사용가능
}
<button onclick="alert('버튼이 클릭됐습니다.')"> Click Me </button>
const aElement = document.querySelector('a');
aElement.addEventListener('click', () => {
alert('a element clicked');
});
const buttonElement document.querySelector('.btn2');
buttonElement.addEventListener('click', (event) => {
let val;
val = event.target;
val = event.target.id;
val = event.target.className;
val = event.target.classList;
val = event.type;
val = event.clientY;
val = event.offset;
console.log(val);
});
load: 문서나 객체가 로드 완료되었을 때 발생함change: 객체의 내용이 변동되거나 focus를 잃었을 때 발생함resize: 객체의 크기가 바뀌었을 때 발생scroll: 스크롤바를 조작할 때 발생error: 에러가 발생했을 때 발생keydown: 키를 눌렀을 때 발생keyup: 키를 눌렀다가 땠을 때 발생keypress: 사용자가 눌렀던 키의 문자가 입력되었을 때 발생click: 객체를 클릭했을 때 발생dblclick: 객체를 더블클릭했을 때 발생mousedown: 마우스를 클릭했을 때 발생mouseout: 마우스가 특정 객체 밖으로 나갔을 때 발생mouseover: 마우스가 특정 객체 위로 올려졌을 때 발생mousemove: 마우스가 움직였을 때 발생mouseup: 마우스에서 손을 떼어내면 발생✨ 팁: VSCode 자동완성? Tabnine AI extention 사용
const submitBtn = document.querySelector('.submit-btn');
const form = document.querySelector('form');
const title = document.querySelector('h2');
// 이벤트 종류별 시도: click event
submitBtn.addEventListener('click', handleEvent);
submitBtn.addEventListener('dblclick', handleEvent);
submitBtn.addEventListener('mousedown', handleEvent);
submitBtn.addEventListener('mouseup', handleEvent);
submitBtn.addEventListener('mouseenter', handleEvent);
submitBtn.addEventListener('mouseleave', handleEvent);
submitBtn.addEventListener('mousemove', handleEvent);
function handleEvent(e) {
e.preventDefault();
console.log(`Event Type: ${e.type}`);
title.textContent = `MouseX: ${e.offsetX} MouseY: ${e.offsetY}`;
}
// form event
const form = document.querySelector('form');
const emailInput = document.getElementById('email');
const title = document.querySelector('h2');
form.addEventListener('submit', handleEvent);
emailInput.addEventListener('keydown', handleEvent);
emailInput.addEventListener('keyup', handleEvent);
emailInput.addEventListener('keypress', handleEvent);
emailInput.addEventListener('focus', handleEvent);
emailInput.addEventListener('blur', handleEvent);
emailInput.addEventListener('paste', handleEvent);
function handleEvent(e) {
if (e.type === 'submit') {
e.preventDefault();
}
console.log(`Event Type: ${e.type}`);
title.textContent = e.target.value;
}



<p>P</p>

this 호출 → 해당 객체 참조const audio = {
title: 'a',
play() {
console.log('play this', this);
}
}
audio.play(); // {title: 'a', play: f} 처럼 해당 객체를 출력
audio.stop = function() {
console.log('stop this', this)
}
// 객체에 stop() { console.log('stop this', this); } 가 더해진 상태
audio.stop() // {title: 'a', play: f, stop: f}
this 호출 → window 객체 참조function playAudio() {
console.log(this);
}
playAudio(); // 윈도우 객체 출력: window {window: Window, self: Window, ...}
this 호출 → 빈 객체를 가리킴function Audio(title){
this.title = title;
console.log(this); // Audio {title: 'a'}가 출력됨
}
const audio = new Audio('a');
title: undefined 인 이유? 함수 안의 this는 window 객체를 가리키는데 window 객체에는 당연하게도 title이 정의되어있지않으므로! forEach(콜백함수, thisArg)에서 thisArg 부분에 넣는 것을 콜백함수에서 this로 참조할 수 있으므로 아래와 같이 수정하면 원래의 의도대로 동작 가능{title: 'audio'}를 this로 대체해도 같은 결과가 나옴const audio = {
title: 'audio',
categories: ['rock', 'pop', 'hiphop'],
displayCategories() {
this.categories.forEach(function(category) {
console.log(`title: ${this.title}, category: ${category}`);
// title: undefined, category: rock
// title: undefined, category: pop
// title: undefined, category: hiphop
})
}
}
// 원래의 의도대로 수정하기 1
const audio = {
title: 'audio',
categories: ['rock', 'pop', 'hiphop'],
displayCategories() {
this.categories.forEach(function(category) {
console.log(`title: ${this.title}, category: ${category}`);
}, {title: 'audio'}) // 또는 {title: 'audio'}를 this로 대체해도 됨
}
}
✨ 생성자 함수 vs 객체
new 키워드로 호출됨function Person(name, age) {
this.name = name;
this.age = age;
}
const person1 = new Person('Alice', 25); // Creates a new object with name 'Alice' and age 25
const person2 = new Person('Bob', 30); // Creates a new object with name 'Bob' and age 30
key: value 형태이며, .으로 불러와서 사용 가능const person = {
name: 'Alice',
age: 25,
greet: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
person.greet(); // Outputs: "Hello, my name is Alice"
this 호출 → 항상 상위 스코프의 this를 가리킴// 원래의 의도대로 수정하기 2
const audio = {
title: 'audio',
categories: ['rock', 'pop', 'hiphop'],
displayCategories() {
this.categories.forEach(function(category) => {
console.log(`title: ${this.title}, category: ${category}`);
})
}
}
this를 사용하면 window 객체를 가리키게 됨 → 참조 대상을 바꿀 수는 없을까? fullName.call(person1);로 호출했으므로 fullName 함수 내의 this 들이 더 이상 window 객체가 아닌, person1 객체를 참조하게 됨const fullName = function() {
console.log(this.firstName + " " + this.lastName);
// Minji Kim
}
const person1 = {
firstName: "Minji",
lastName: "Kim"
}
fullName.call(person1);
불러올함수.call(참조할 객체, 인수A, 인수B)를 불러올함수(인수a, 인수b)로 받아와서 함수 내에서 사용할 수 있음!const fullName = function(city, country) {
console.log(this.firstName + " " + this.lastName);
// Minji Kim
console.log("Lives in " + city, country);
// Lives in Seoul South Korea
}
const person1 = {
firstName: "Minji",
lastName: "Kim"
}
fullName.call(person1, "Seoul", "South Korea");
const fullName = function(city, country) {
console.log(this.firstName + " " + this.lastName);
// Minji Kim
console.log("Lives in " + city, country);
// Lives in Seoul South Korea
}
const person1 = {
firstName: "Minji",
lastName: "Kim"
}
fullName.apply(person1, ["Seoul", "South Korea"]);
func.bind(greeting);는 func 함수 내의 this에 greeting이라는 객체를 binding만 시켜주는 것이므로 실행하기 위해서는 const boundFunc로 담아서 따로 호출해줘야 함function func(language) {
if(language == "kor") {
console.log(`language: ${this.korGreeting}`);
} else {
console.log(`language: ${this.engGreeting}`);
}
}
const greeting = {
korGreeting: '안녕',
engGreeting: 'Hello',
}
const boundFunc = func.bind(greeting);
boundFunc('kor');
// 기존의 조건문
if (a) {
a = "a";
} else {
a = "b";
}
// 삼항연산자
a ? a = "a" : a = "b";
setTimeout(호출될함수, 지연시간ms) : 전역 메소드인 setTimeout() 메소드는 만료된 후 함수나 지정한 코드 조각을 실행하는 타이머를 설정함// 동기(Synchronous, 시간을 맞춤. 순차적으로 진행되어야 함)
console.log('1');
// 비동기(Asynchronous, 시간을 맞추지 않음, 동시다발적으로 진행 가능)
setTimeout(() => {
console.log('2');
}, 3000);
// 동기
console.log('3');
동기(Synchronous) vs 비동기(Asynchronous): 동기는 순차적으로 진행되어야하며, 앞의 일을 끝내지 못하면 그 다음 단계의 일을 수행할 수 없지만, 비동기는 동시다발적으로 여러 일을 진행할 수 있음

자바스크립트는 동기 언어이므로 비동기 부분을 실행할 때에는 브라우저의 api를 활용하게 됨

자바스크립트 엔진: 메모리힙 + 호출스택

(1) 메모리힙: 메모리 할당이 발생하는 곳으로, 변수를 정의하면 저장이 되는 창고
(2) 호출 스택: 코드가 실행될 때 스택들이 이곳에 쌓이게 됨
call stack의 작동 살펴보기
function B() {
setTimeout(function () {
console.log('B-1...');
}, 1500);
}
function A() {
console.log('A-1...');
B();
console.log('A-2...');
}
A();
// 실행결과
// A-1...
// A-2...
// B-1...
만약 setTimeout(f, 0)의 지연시간이 0이라면 0초 후에 (즉, 즉시실행) 실행되는 것을 보장할까?
아님. 0초 이후에 setTimeout 함수가 호출되는 것을 보장하는거지 콜백함수f가 0초 이후에 호출되는 것을 보장하는 것은 아님
Call stack size exceeded: 재귀함수 호출이 계속해서 일어날 때 발생하는 오류

function foo() {
foo();
}
foo();
innerFunction 가 있는 경우 외부 함수 outerFunction 가 실행을 완료하고 해당 변수가 해당 함수 외부에서 더 이상 엑세스 할 수 없는 경우에도 해당 함수 내부 함수는 외부 함수의 변수 및 범위에 엑세스할 수 있음function outerFunction(outerVariable) {
return function innerFunction(innerVariable) {
console.log('Outer Variable: ' + outerVariable);
console.log('Inner Variable: ' + innerVariable);
}
}
const newFunction = outerFunction('outside'); // outerFunction 호출은 이미 여기에서 끝났어야 함
newFunction('inside'); // 그러나 이 부분에서도 outside는 유지됨
outerFunction('outside')는 변수 const newFunction에 할당 되는 즉시 호출됨console.log(newFunction)으로 찍어보면 아래의 return 문이 그대로 출력됨return function innerFunction(innerVariable) {
console.log('Outer Variable: ' + outerVariable);
// Outer Variable: outside
console.log('Inner Variable: ' + innerVariable);
// Inner Variable: inside
}
outerFunction은 outerFunction(outerVariable) 대신 innerFunction(innerVariable)을 반환함newFunction('inside') 를 호출함. 이 때, innerFunction은 원래 outerFunction('outside')로 설정한 outerVariable 매개변수를 기억하고 접근할 수 있음.'inside'로만 호출되었다고 하더라고 'outside'과 'inside'를 모두 출력할 수 있음// 1. 아무 문제 X
let a = 'a';
function functionA() {
let b = 'b';
console.log(a, b);
}
functionA(); // a b
// 2. 오류!!
let a = 'a';
function functionB() {
let c = 'c'
console.log(a, b, c); // b is not defined 오류!!!
}
function functionA() {
let b = 'b';
console.log(a, b);
functionB();
}
functionA();
// 3. 2의 문제 closure를 사용해서 해결하기
// functionB를 functionA 안으로 이동시키기~
let a = 'a';
function functionA() {
function functionB() {
let c = 'c';
console.log(a, b, c);
}
let b = 'b';
console.log(a, b);
functionB();
}
functionA();
function animal (data) {
let name = data.name,
color = data.color,
legNum = data.legNum,
}
let animal (data) {
let {name, color, legNum} = data;
}
let person = {
name: "Minji",
age: 22,
phone: "12315",
address: {
zipcode: 1234,
street: "manfred borner strase",
number: 58
}
}
let {address: {zipcode, street, number}} = person;
console.log(zipcode, street, number); // 1234 manfred borner strase 58
let a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(rest); // [30, 40, 50]
// 전부 받아오는 것이 아닌 선택적으로 받아오고 싶을 때
const numbers = [1, 2, 3, 4, 5, 6];
const [,,three,,five] = numbers;
...의 형태임. let arr1 = [1, 2, 3];
let arr2 = [4, ...arr1, 5, 6]; // 4, 1, 2, 3, 5, 6이 출력
let obj1 = {
a:1,
b:2,
};
let obj2 = {
...obj1, // a:obj1.a, b:obj1.b 이렇게 쓰는 것과 동일
c:3,
d:4,
};
function funcA(p1, p2, p3) {
console.log(p1, p2, p3);
};
funcA(...arr1); // 이런 식으로 매개변수도 배열을 풀어서 전달 가능
map() 메소드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환함const arr = [1, 4, 9, 16];
const map1 = arr.map(x => x * 2);
console.log(map1); // [2, 8, 18, 32]
arr.map(콜백함수, thisArg)로도 사용가능const map2 = arr.map(function (item, index, array) {
console.log(item, index, array, this)
return (item * 2)
}, {a : 'a'});
console.log(map2);
filter() 메소드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환함const words = ['apple', 'orange', 'banana', 'lime', 'blueberry', 'grape'];
const result = words.filter(word => word.length > 5);
console.log(result);
arr.filter(콜백함수, thisArg)const words = ['apple', 'orange', 'banana', 'lime', 'blueberry', 'grape'];
const result = words.filter(function (word, index, array) {
console.log(word, index, array, this);
return word.length > 5
}, {a : 'a'});
console.log(result);
reduce() 메소드는 배열의 각 요소에 대해 주어진 reducer 함수를 실행하고 하나의 결과값을 반환함. 주로 값의 합산에서 많이 사용됨. arr.reduce(reducer함수(accumulator, currentValue, currentIndex, array), initialValue)
accumulator : 누산기// 기본값이 없을 때
[0, 1, 2, 3, 4].reduce(function (accumulator, currentValue, currentIndex, array) {
return accumulator + currentValue;
});

// 기본값 = 10
[0, 1, 2, 3, 4].reduce(function (accumulator, currentValue, currentIndex, array) {
return accumulator + currentValue;
}, 10);

( // 첫번째 소괄호
function () {
// Where magic happens
}
)() // 두번째 소괄호
(
function () {
var aName = 'Barry';
// IIFE 내부에서 생성된 변수이므로 외부에서는 접근불가
}
)();
console.log(aName); // ReferenceError: aName is not defined.
var result = (function() {
var name = "minji";
return name;
})();
console.log(result); // minji
// 함수 호출 없이도 바로 실행
function, 함수 이름(선택) name, 매개변수 집합 (a, b), 함수 본문 return a - b; 등으로 구성됨. function name (a, b) { // 함수의 이름(name)이 없어도 됨
// 단, 아래의 두가지 조건을 충족해야 함
return a - b; // 함수 본문
}
// (1) 해당 함수를 할당받을 변수를 지정해야 함
const minus = function(a, b) {
return a - b;
}
// (2) 해당 함수를 즉시 호출해야 함
(function (a, b) {
return a - b;
})(1, 2);
!function() { return console.log("hi") }()
void function() { return console.log("hi") }()
+function() { return console.log("hi") }()
-function() { return console.log("hi") }()
~function() { return console.log("hi") }()
*function() { return console.log("hi") }()
^function() { return console.log("hi") }()
&function() { return console.log("hi") }()
const score = () => {
let count = 0;
return {
current: () => { return count },
increment: () => { count++ },
reset: () => { count = 0 }
}
}
console.log(typeof score); // function
console.log(score);
/*() => {
let count = 0;
return {
current: () => { return count },
increment: () => { count++ },
reset: () => { count = 0 }
}
}*/
console.log(score().current()); // 0
score().increment(); // count++를 계산
console.log(score().current()); // 0: 1로 증가할 줄 알았는데 여전히 0!
// 호출할 때마다 count=0;으로 초기화되기 때문
// 그렇다면 1로 증가시키려면 어떻게 해야할까?
const score = (() => {
let count = 0;
return {
current: () => { return count },
increment: () => { count++ },
reset: () => { count = 0 }
}
})() // 괄호로 묶어서 즉시실행함수로 변경해줌
console.log(score().current()); // 0
score().increment(); // count++를 계산
console.log(score().current()); // 1로 변경됨! :>
const increment = () => {
let counter = 0;
console.log(counter);
const number = (num) => {
console.log(`It is ${num} number`);
}
return () => { counter++; number(counter); }
}
increment();
increment();
const increment = (() => {
let counter = 0;
console.log(counter);
const number = (num) => {
console.log(`It is ${num} number`);
}
return () => { counter++; number(counter); }
})() // 괄호를 씌워서 즉시실행함수로 만듦
increment(); // It is 1 number
increment(); // It is 2 number
기본적으로 브라우저 viewport와 설정한 요소의 교차점을 관찰하며, 요소가 viewport에 포함되는지 포함되지 않는지, 즉 사용자 화면에 지금 보이는 요소인지 아닌지를 구별하는 기능을 제공함
비동기적으로 실행되는 기능이므로 scroll 같은 이벤트 기반의 요소 관찰에서 발생하는 렌더링 성능이나 이벤트 연속 호출 같은 문제 없이 사용 가능
주로 무한스크롤 (instagram feed) 등을 구현할 때 사용됨

예를 들어서, 스크롤을 아래방향으로 내려서 4번째 사각형에 도달하면 가지고 있는 더 많은 내용들을 불러와서 보여주는 방식

디폴트 js 코드 형태
// script.js
const observer = new IntersectionObserver(
function (entries, observer) {
if (entry.isIntersecting) {
// 타깃요소와 루트요소가 교차할 때 실행하고자 하는 일을 서술
}
},
{
root: null,
threshold: 1,
}
);
cong imgs = document.querySelectorAll('img')
observer.observe(관찰대상)
<!--html-->
<head>
<style>
.item {
text-align: center;
padding: 20px 0px;
margin: 0px;
}
.item:nth-child(even) {
background-color: lightcoral;
}
</style>
</head>
<body>
<div class="list"></div>
<p class="end"></p> <!--관찰될 p태그!-->
<script src="script.js"></script>
</body>
// script.js
const count = 20 // 한번에 추가되는 새로운 item의 개수
let itemIndex = 0 // item의 index
let observer = new IntersectionObserver(entries => { // 콜백함수!!
entries.forEach(entry => {
const list = document.querySelector('.list')
// 타겟 요소와 루트 요소가 교차함 → inIntersecting = true
if (entry.isIntersecting) { // entry는 한 개 (p태그)
for (let i = itemIndex; i < itemIndex + count; i++){
// item을 count 숫자만큼 생성하고 list에 추가하기
let item = document.createElement('p')
item.textContent = i;
item.className += 'item';
list.appendChild(item)
}
// itemIndex를 +count 해서 갱신
itemIndex = itemIndex + count
}
})
}, { root: null, threshold: 0.1 })
// null을 설정하거나 무엇도 설정하지 않으면 브라우저 viewport가 기준이 됨
// threshold 0.1은 타겟요소의 10%가 루트요소와 겹치면 콜백을 실행한다는 의미
// list의 끝부분을 알려주는 p타겟요소 관찰 시작
observer.observe(document.querySelector('.end'))
entries를 콘솔창에 찍어보면 아래와 같은 화면이 나옴

두번째 예시: 모든 이미지를 고해상도로 보여주기에는 지나친 자원이 필요하므로, 화면 밖의 이미지들은 400X300 등의 미리보기로 표현하고, 이미지들이 viewport 내로 들어오게 되면 그때부터 고해상도 원본을 표시하고자 한다.
<!--html-->
<head>
<style>
.img {
width: 400px;
height: 300px;
display: block;
margin: 10px auto;
}
</style>
</head>
<body>
<img
src="https://via.placeholder.com/400x300"
data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300"
/>
<img
src="https://via.placeholder.com/400x300"
data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300"
/>
<img
src="https://via.placeholder.com/400x300"
data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300"
/>
<img
src="https://via.placeholder.com/400x300"
data-src="https://ik.imagekit.io/demo/img/image4.jpeg?tr=w-400,h-300"
/>
<script src="script.js"></script>
</body>
// script.js
const observer = new IntersectionObserver(
function (entries, observer) {
entries.forEach(entry => { // entries는 4개짜리 배열임 (img 태그가 현재 4개이므로!)
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src
// 고화질원본이미지로 바꿔준 후에는 더이상 관찰할 필요 없음
// 관찰 중단
observer.unobserve(entry.target)
}
})
},
{
threshold: 1,
}
);
const imgs = document.querySelectorAll('img')
imgs.forEach(img) => { // 각각의 img 태그를 모두 관찰
observer.observe(img)
})
entries를 화면에 찍어보면 다음과 같은 화면이 나옴
const add = (x, y) => x + y;
console.log(add(10, 20));
const fullName = (first, last) => `${first} ${last}`;
console.log(fullName('Minji', 'kim');
const z = 1;
// sum 함수는 함수 바깥의 scope에 접근하고 있으므로 impure 함수이다
const sum = (x, y) => x + y + z;
console.log(sum(10, 20));
함수와 함께 사용되는 고급기술로, 자바스크립트 뿐만 아니라 다른 언어에도 존재함.
f(a, b, c) 처럼 단일 호출로 처리하는 함수를 f(a)(b)(c) 처럼 각각의 인수가 호출 가능한 프로세스로 호출된 후 병합될 수 있게 변환하는 것
즉, 함수를 호출하는 것이 아닌 변환하는 것임
예시 1
// this method is cleaner
const sum = (x, y) => x + y;
const curriedSum = x => y => x + y;
console.log(sum(10, 20)); // 30
console.log(curriedSum(10)); // y => x + y
console.log(curriedSum(10)(20)); // 30
// 예시 2
const makeFood = (ingred1) => {
return (ingred2) => {
return (ingred3) => {
return `${ingred1} + ${ingred2} + ${ingred3}`
}
}
}
const hamburger = makeFood("bread")("meat")("lettuce");
console.log(hamburger) // bread + meat + lettuce

// non-curry
function log(date, importance, message) {
alert(`[${date.getHours()}: ${date.getMinutes()}]: [${importance}] ${message}`);
}
log(new Date(), "DEBUG", "some bug");
// currying function
function curry(f) {
return function (a) {
return function (b) {
return function (c) {
return f(a, b, c);
}
}
}
}
const curriedLog = curry(log);
// calling curried log function
curriedLog(new Date())("DEBUG")("some bug");
// currying function dynamic ver.
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
else {
return function (...args2) {
return curried.apply(this, args.concat(args2));
}
}
}
}
// 사용 예시
const sum = (x, y, z, j) => x + y + z + j;
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)(4)); // 10
"use strict" 지시자 입력: 만약 특정 함수 내부에 작성하면 해당 함수만 strict mode가 됨!

class 를 생성하면 자동으로 strict 모드로 바뀜
script 로드 시 type="module"을 작성하면 자동으로 strict 모드로 바뀜
<script src="script.js" type="module"></script>
class Car {
constructor() { ... }
method1() { ... }
method2() { ... }
}
class Animal {
constructor() { ... }
method1() { ... }
method2() { ... }
}
Abstraction(자료 추상화) : 불필요한 정보는 숨기고 중요한 정보만을 표현함으로서 프로그램을 간단히 만드는 것 → 객체 안의 자세한 내용은 몰라도 중요 정보를 이용해서 객체를 간단히 사용 가능
예: 커피머신의 작동원리는 몰라도 커피머신을 이용할 수는 있음
Inheritance(상속): 새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수있게 하는 기능
상속을 받는 새로운 클래스를 파생클래스, 하위클래스, 자식클래스라고 하며, 종속관계를 형성함
Polymorphism(다형성): poly는 많은, morph는 형태라는 뜻으로 다양한 형태를 가질 수 있다는 개념임
같은 메소드라도 각 인스턴스에 의해 다양한 형태를 가질 수 있다는 개념
Encapsulation(캡슐화): 클래스 안에 관련 메소드, 변수 등을 하나로 묶어주고, 이를 이용해서 바깥으로부터의 접근을 막아 보안이 강화되고 잘 관리되는 코드를 제공
class PaymentGateway {
constructor() {
this.connect();
}
connect() {
// 결제 제공업체에 연결
}
pay(amount) {
//...
}
refund(amount) {
//...
}
}
class Paypal extends PaymentGateway {
pay(amount) {
// paypal 전용 로직 구현
}
}
class Visa extends PaymentGateway {
pay(amount) {
// Visa 전용 로직 구현
}
}
class Customer {
makePayment(gateway, amount) {
return gateway.pay(amount)
}
// 만약 다형성이 없다면 여기서 메소드들을 생성해야 함
// payByPaypal(amount) {}
// payByVisa(amount) {}
getRefund(gateway, amount) {
return gateway.refund(amount)
}
}
// 하지만 다형성에 의해서, customer class는 수정하지 않아도 됨! 즉, 새로운 결제방식이 생길때마다 기존의 class를 수정하는 방식이 아닌, 새 class를 만드는 방식으로 작동함
const john = new Customer();
const paypal = new Paypal();
const visaCard = new Visa();
john.makePayment(paypal, 100);
john.makePayment(visaCard, 100);
let user = {
name: "minji",
age: 22,
email: "minzikx@gmail.com",
}
console.log(user.name); // minji
console.log(user.hasOwnProperty("email")); // true
hasOwnProperty ?

prototype ? : 프로토타입은 자바스크립트 객체가 다른 객체로부터 메소드와 속성을 상속받는 메커니즘을 말함
// 생성자 함수 작성
function Person(name, age, birthday) {
this.name = name;
this.age = age;
this.birthday = new Date(birthday);
this.calculateAge = function() {
const diff = Date.now() = this.birthday.getTime();
const ageDate = new Date(diff);
return Math.abs(ageDate.getUTCFullYear() - 1970);
}
}
// 객체 생성
const minji = new Person('minji', 22, '4-19-03');
console.log(minji);
minji던 john이던 birthday, age, name 의 값은 모두 다르겠지만 calculateAge 프로퍼티의 값은 같음생성자함수.prototype.메소드// 프로토타입에 넣어주기 방법 1
Person.prototype.calculateAge = function() {
const diff = Date.now() = this.birthday.getTime();
const ageDate = new Date(diff);
return Math.abs(ageDate.getUTCFullYear() - 1970);
}
Object.create()function Person(name, age, birthday) {
let person = Object.create(personsPrototype); // 새 객체를 만듦
person.name = name;
person.age = age;
person.birthday = new Date(birthday);
return person;
}
const personsPrototype = {
calculateAge() {
const diff = Date.now() = this.birthday.getTime();
const ageDate = new Date(diff);
return Math.abs(ageDate.getUTCFullYear() - 1970);
}
}
class Person {
constructor(name, age, birthday) {
this.name = name;
this.age = age;
this.birthday = new Date(birthday);
}
.introduce() { // 프로토타입으로 들어감
return `Hello my name is ${this.name}`;
}
}
const minji = new Person('minji', 22, '4-19-03');
static : 프로토타입이 아닌, 클래스 함수 자체에 메소드를 설정할 수도 있음. 이러한 메소드를 정적 메소드라고 부름.this.name 같은 것들을 사용하지 않는, 독립적인 것을 정의할 때 사용함
class Person {
constructor(name, age, birthday) {
this.name = name;
this.age = age;
this.birthday = new Date(birthday);
}
introduce() { // 프로토타입으로 들어감
return `Hello my name is ${this.name}`;
}
static multipleNumbers(x, y) {
return x * y;
}
}
console.log(Person.multipleNumbers(2, 9));

extends 키워드를 사용해서 부모 클래스에 있던 기능을 토대로 자식 키워드를 만들어, 부모 클래스를 자식 클래스에 확장할 수 있음super()를 사용함class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
introduce() {
return `Hello my name is ${this.name}`;
}
}
class Client extends Person {
constructor(name, email, phone, address) {
super(name, email)
this.phone = phone;
this.address = address;
}
}
const minji = new Client('minji', 22, '010-0000-1111', '서울');
console.log(minji.introduce) // Hello my name is minji
minji.introduce가 실행되는 순서

new를 붙여서 new User('minji') 인스턴스 객체로 생성하면 넘겨받은 인수와 함께 constructor가 실행됨'minji가 this.name에 할당됨class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
let user = new User('minji');
user.sayHi();
super(인수들) : 자식 클래스 Model 내에서 부모 클래스의 생성자 super(brand) /메소드 super.present() 를 호출할 때 사용됨class Car {
constructor(brand) { // 부모 클래스의 생성자
this.carname = brand;
}
present() { // 부모 클래스의 메소드
return `I have a ` + this.carname;
}
}
class Model extends Car {
constructor(brand, mod) {
super(brand);
this.model = mod;
}
show() {
return super.present() + `, it is a ` + this.model;
}
}
let mycar = new Model("Ford", "Mustang");
mycar.show();
자바스크립트는 하나의 스레드로 이루어져 있음 ▷ 한번에 하나의 일밖에 못함
↪ 그런데 만약 이 하나의 일이 오래 걸리는 일이라면? UX가 굉장히 부정적이게 됨

위의 문제점을 해결하기 위해 비동기로 어떠한 일을 수행하게 됨

만약 아래의 코드와 같이, 비동기 요청이 여러개 있을 때 하나의 요청이 다른 요청의 결과에 의존한다면? 즉, 두번째 요청에 첫번째 요청의 결과가 필요하다면?
✨ 해결 방법: (1) Callback 함수 (2) promise (3) Async/Await
↪ 도입 순서대로 적혀있으며, 최근에는 Async/Await를 가장 많이 사용하는 추세
// 1st response
const response1 = request('http://abc.com');
// 2nd response
const response2 = request('http://def.com', response1);
function firstFunction(parameters, callback) {
const response1 = request(`http://abc.com?id=${parameters.id}`);// 요청
callback(response1);
}
function secondFunction(response1, callback) {
const response2 = request(`http://def.com`, response1);
callback();
}
firstFunction(para, function(response1) {
secondFunction(response1, function() {
thirdFUnction(para, function() {
//...
})
})
})
new 키워드와 생성자를 사용해서 만듦promise 객체는 비동기 작업이 맞이할 미래의 완료 or 실패와 그 결과값을 나타냄const myFirstPromise = new Promise((resolve, reject) => {
// resolve() : 비동기 작업을 성공적으로 완료해 결과를 값으로 반환할 때 호출
// reject() : 작업이 실패해서 오류의 원인을 반환할 때 호출, 주로 오류객체를 받음
});
function fetchData() {
return new Promise((resolve, reject) => {
const success = true;
if (sucess) {
resolve('성공');
} else {
reject('실패');
}
})
}
fetchData()
.then(function (result) {
console.log(result);
})
.then(function (error) {
console.log(error);
})
catch를 사용함myPromise
.then((result) => {
console.log(result);
})
.catch((err) => {
console.log(err);
})
.finally(() => { // 이행이던 거부던 무조건 마무리는 여기로
console.log('---every process ended---');
})
promise 객체는 대기(pending, 비동기 처리 로직이 아직 완료되지 않은 상태), 이행(fulfilled, 비동기 처리가 완료되어 promise가 결과값을 반환해준 상태), 거부(rejected, 비동기처리가 실패하거나 오류가 발생한 상태)의 세가지 상태 중 하나를 가짐!

promise() 생성자는 promise를 지원하지 않는 함수를 감쌀때만 사용하므로 fetch 함수에는 사용하지 않음
// 자동으로 비동기로 받아오는 중
fetch('http://blahblah/1')
.then(response1 => response1.json()) // 받아와서 json으로 바꾸기
.then(json1 => console.log(json1)); // json으로 받아오기
// 요청이 끝난 후 다시 fetch를 하고 싶다면?
.then(() => fetch('http://blah/2'));
// 위와 동일한 방식으로 받아오기
.catch((error) => {
console.error(error);
})
.finally(() =>
console.log('작업끝'); // 오류가 나도 실행됨
})
promise.all() : 해당 메소드는 array처럼 순회 가능한 객체에 주어진 모든 프로미스가 이행한 후 결과를 array로 반환함const promise1 = Promise.resolve(3); // 만약 얘가 reject라면 실패한이유 반환
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// Expected output: Array [3, 42, "foo"]
promise.race() : iterable 내의 프로미스 중 가장 먼저 완료된 것의 결괏값 하나만을 반환함const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster
});
// Expected output: "two"
async로 감싸고 fetch 앞에 await을 붙여주는 형태async function makeRequests() {
try {
const response1 = await fetch('http://blah.com');
const jsonResponse1 = await response1.json();
console.log(jsonResponse1);
} catch (error) {
console.error(error);
} finally {
console.log('---모든작업끝---');
const sym1 = Symbol();
const sym2 = Symbol();
console.log(sym1 === sym2); // false
const sym3 = Symbol("hi");
console.log(sym1); // Symbol()
console.log(sym3.description); // hi
symbol은 언제 사용될까? 어떤 객체의 프로퍼티 내용들은 모른다고 가정하자. 이 때, 객체에 유니크한 값을 추가하고 싶은데 아무 프로퍼티명이나 carA.id = 300 같은 식으로 불러서 추가할 경우 이미 존재하는 속성값을 오버라이딩 (1 → 300) 하는 경우가 발생할 수 있음let carA = {
id: 1,
name: 'morning',
brand: 'kia',
price: 1000
}
const idSym = Symbol('id');
carA[idSym] = 300;
console.log(carA);
// 심볼은 프로퍼티로 보여지지는 않음
console.log(Object.getOwnPropertyNames(carA))
// ['id', 'name', 'brand', 'price']
for (const key in carA) {
console.log(key);
} // id name brand price
// 심볼을 확인하려면,
console.log(Object.getOwnPropertySymbols(carA)); // [Symbol(id)]

symbol.for() 를 이용해서 전역심볼 만들기: 원래는 심볼로 값을 생성하면 심볼의 description이 같더라도 다 다른 값을 가지게 됨. 그러나 symbol.for()를 이용하면 같은 description을 가졌을 때 같은 값을 가지며, 전역심볼이 되어서 다른 곳에서 descriptionconsole.log(Symbol('id') === Symbol('id')) // false
console.log(Symbol.for('id') === Symbol.for('id')) // true
Symbol.keyFor() : symbol.for() 를 이용해서 만든 전역심볼을 찾기 위해 description을 얻음let sym = Symbol.for('id');
alert(Symbol.keyFor(sym)); // id
// 예시 1
const RED = 'red'; // Symbol('red')
const ORANGE = 'orange'; // Symbol('orange')
const YELLOW = 'yellow'; // Symbol('yellow')
const BLUE = 'blue'; // Symbol('blue')
const DOG = 'blue';
function getImportanceLevel(color) {
switch (color) {
case RED:
return 'very important';
case ORANGE:
return 'important';
case YELLOW:
return 'a bit important';
case BLUE:
return 'not so important';
default:
console.log(`${color} not included`);
}
}
console.log(getImportantLevel(BLUE)); // not important
console.log(getImportantLevel(dog)); // blue not included 이 나와야 하는데 not important가 나옴
// 위의 주석대로 symbol로 수정하기
// 예시 2: 사진에서 length 3은 제외하고 출력하고 싶다면?
const length = Symbol('length'); // 심볼이 되면 프로퍼티에서 빠지니까 출력도 안됨
class Car {
consturctor() {
this[length] = 0; // []로 감싸줘야 함
}
add(brand, name) {
this[brand] = name;
this[length]++;
}
}
let myCars = new Car();
// adding cars
myCar.add('kia', 'morning');
myCar.add('hyundai', 'tuscon');
myCar.add('genesis', 'gv80');
for (const car in myCars) {
console.log(car, myCars[car]);
}

for ... of를 사용할 수 있거나 [Symbol.iterator]()가 값을 가지면 iteratable함next()를 호출해서 {value: , done: } 두개의 속성을 가지는 객체를 반환하는 객체[Symbol.iterator]().next()?
// iterator 직접 생성해보기
function makeIterator(numbers) {
let nextIndex = 0;
return {
next: function() {
return nextIndex < numbers.length ?
{ value: numbers[nextIndex++], done:false }:
{ value: undefined, done: true }
}
}
}
const numbersArr[1, 2, 3]; // iteratable
const numbersIterator = makeIterator(numbersArr); // iterator
console.log(numbersIterator.next()); // {value: 1, done: false}
console.log(numbersIterator.next()); // {value: 2, done: false}
console.log(numbersIterator.next()); // {value: 3, done: false}
console.log(numbersIterator.next()); // {value: undefined, done: true}
// [Symbol.iterator]() 사용해보기
const numbersArr[1, 2, 3]; // iteratable
const numbersIterator = numbersArr[Symbol.iterator]()
console.log(numbersIterator.next()); // {value: 1, done: false}
console.log(numbersIterator.next()); // {value: 2, done: false}
console.log(numbersIterator.next()); // {value: 3, done: false}
console.log(numbersIterator.next()); // {value: undefined, done: true}
yield는 함수를 일시적으로 멈춰줌. // generator ex
function* sayNumbers(i) {
yield 1; // yield* [1, 2, 3]; 과 같은 표현
yield 2;
yield 3;
}
const number = sayNumbers();
console.log(number.next().value); // 1
console.log(number.next().value); // 2
console.log(number.next().value); // 3
function* createIds() {
let index = 1;
while (true) {
yield index++;
}
}
const gen = createIds();
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);