Document Object Model
1) getElementsByTagName
const allImages = document.getElementsByTagName('img')
for (let img of allImages) {
console.log(img.src)
}
//이미지 출처 주소를 알수있음 (src)
2) getElementsByclassName
const squareImages = document.getElementsByClassName('square')
for(let i of squareImages) {
img.src = '';
}
ALL-IN-ONE method to select a single element.
//<p> 태그안에 존재하는 anchor 태그 조회
const links = document.querySelectorAll('p a');
for ( let link of links) {
console.log(link.href);
}
getAttribute
setAttribute
Manipulating Attributes Practice
const img = document.querySelector('img');
img.setAttribute('src', 'https://devsprouthosting.com/images/chicken.jpg')
img.alt = 'chicken'
방법 1
Point : 1) 스타일적용시 속성에 '-'가 아닌 카멜케이스 사용 (ex.fontSize)
2) 스타일적용시 value값에는 항상 '' 사용 (문자열만)
-> 선호되는 방법은 아님.
Magical Forest Circle Exercise
const div = document.querySelector('#container');
const img = document.querySelector('img');
div.style.textAlign = 'center'
img.style.width = '150px'
img.style.borderRadius = '50%'
Rainbow Text Excercise
const colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'];
//YOU CODE GOES HERE:
const ele = document.querySelectorAll('span');
for(let element of colors) {
ele[0].style.color = 'red'
ele[1].style.color = 'orange'
ele[2].style.color = 'yellow'
ele[3].style.color = 'green'
ele[4].style.color = 'blue'
ele[5].style.color = 'indigo'
ele[6].style.color = 'violet'
}
toggle
-> 손쉽게 class 추가/제거 할 수 있음.
ClassList Practice
const li = document.querySelectorAll('li');
for (let ele of li) {
ele.classList.toggle('highlight')
}
ParentElement
nextElementSibling
previousElementSibling
AppendChild
Append (맨 끝에 추가됨)
prepend
insertAdjacentElement
100 Button Insanity Exercise
const container = document.querySelector('#container')
for(let i = 0; i<=99; i++) {
const button = document.createElement('button');
button.innerText = 'HEY'
container.appendChild(button)
}
better way (remove)
const container = document.querySelector('#container')
const baseURL = 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/';
for (let i =0; i<10; i++){
const pokemon = document.querySelector('div') //div
pokemon.classList.add('pokemon') //div에 pokemon 클래스명 추가
const label = document.querySelector('span')
label.innerText = `#${i}` //네이밍
const newImg = document.createElement('img')
newImg.src = `${baseURL}${i}.png`
pokemon.appendChild(newImg) //div태그 자식 추가
pokemon.appendChild(label) //div태그 자식 추가
container.appendChild(pokemon); //container => div의 부모
}
// <div>
//<img>
//<span> ...
EVENTS
const button = document.querySelector('#v2')
button.onclick = function() {
console.log("You Clicked me !")
}
function scream() {
console.log("AHHHAAHAHHA")
}
button.onmouseenter = scream;
//함수를 '호출'하는것이 아닌 해당 객체상의 특성으로 설정하는 것 뿐임.
<함수설정>
1)
button.addEventListener("click", function() {
alert("clikc!")
})
<함수로 적용>
2)
function scream() {
alert("AHAHHA!!")
}
button.addEventListener("click", scream);
Click Events Exercise
const hello = document.querySelector('#hello');
const goodbye = document.querySelector('#goodbye')
hello.addEventListener("click", function() {
console.log("hello")
})
goodbye.addEventListener("click" , function() {
console.log("goodbye");
})
const button = document.querySelector('button');
const h1 = document.querySelector('h1');
const r = Math.floor(Math.random() * 256) + 1;
const g = Math.floor(Math.random() * 256) + 1;
const b = Math.floor(Math.random() * 256) + 1;
button.addEventListener("click", function(){
if(r + g + b < 100) {
h1.style.color = 'white';
} else {
h1.style.color = 'black';
}
const newColor = makeRandomColor();
document.body.style.backgroundColor = newColor;
h1.innerText = newColor;
})
const makeRandomColor = () => {
const r = Math.floor(Math.random() * 256) + 1;
const g = Math.floor(Math.random() * 256) + 1;
const b = Math.floor(Math.random() * 256) + 1;
return `rgb(${r},${g},${b})`
}
const makeRandomColor = () => {
const r = Math.floor(Math.random() * 256) + 1;
const g = Math.floor(Math.random() * 256) + 1;
const b = Math.floor(Math.random() * 256) + 1;
return `rgb(${r},${g},${b})`
}
const buttons = document.querySelectorAll('button');
const h1s = document.querySelectorAll('h1');
for (let button of buttons) {
this.addEventListener('click', function() {
this.style.backgroundColor = makeRandomColor();
})
}
for (let h1 of h1s) {
this.style.backgroundColor = makeRandomColor();
this.style.color = makeRandomColor();
}
function colorize() {
this.addEventListener("click", function() {
this.style.backgroundColor = makeRandomColor();
this.style.color = makeRandomColor();
})
}
이벤트 객체는 모든 이벤트 핸들러에 엑세스하며 자동으로 전달된다.(매게변수: event, evt, e)
const input = document.querySelector('input');
input.addEventListener('keydown', function(e){
console.log(e.key)
console.log(e.code)
})
const tweetForm = document.querySelector('#tweetForm') //form 아이디명
const container = document.querySelector('#tweets') // ul 아이디명
//submit 할때 실행되는 함수
tweetForm.addEventListener('submit', function(e) {
e.preventDefault(); //이벤트(form의 action)의 기본동작을 실행못하게함
const usernameInput = tweetForm.elements.username; //form의 element(input태그)의 username(input에 부여된 id 값)
const tweetInput = tweetForm.elements.tweet; //tweet은 id로 부여된 이름임.
addTweet(username.value, tweet.value);
usernameInput.value = ' '; // username 입력 후 입력창 초기화
tweetInput.value = ' '; // tweet 입력후 입력창 초기화
})
const addTweet = (username, tweet) => {
const newTweet = document.createElement('li')
const bTag = document.createElement('b') //볼드체 추가
bTag.append(usernameInput); //username에 볼드체 추가
newTweet.append(bTag) //li에 볼드체태그 적용된 username 추가
newTweet.append(`- ${tweetInput}`)
container.append(newTweet); //ul에 li 추가
}
elements 는 순서대로 정렬된 '집합' 입력에 name을 부여하면 각 입력에 name으로 access 가능
Ex) tweetForm.elements.(username/tweet) , ( ) 안은 내가 접근하고 싶은 값.
실시간으로 내가 입력한 값이 브라우저에 나타나게 만듦.
const input = document.querySelector('input');
const h1 = document.querySelector('h1');
input.addEventListener('input', function(e){
h1.innerText = input.value;
})
Input Event Exercise
const input = document.querySelector('input')
const h1 = document.querySelector('h1');
input.addEventListener('input', function(e){
h1.innerText = `Welcome, ${input.value}`
let inputValue = input.value
if (inputValue === '') {
h1.innerText = "Enter Your Username"
}
})
이벤트 위임은 이벤트 수신기가 추가된 시점에 페이지에 없었던 요소를 다루어야 하는 상황에 적용.
const lis = document.querySelectorAll('li')
for (let li of lis) {
li.addEventListener('click', function(e){
li.remove();
})
}
const container = document.querySelector('#tweets') // ul 아이디
//이벤트 위임은 목표 요소의 '부모'요소에 적용을 시켜주는것 (li의 부모요소인 ul)
container.addEventListener('click', function(e){
e.target.nodeName === 'LI" && e.target.remove();
})
"target" 속성 사용 !! - traget 이 'li'로 되어있으므로 li 를 눌렀을 때 remove가 가능한것. 추가적으로 nodeName 속성으로 내가 이벤트를 적용시키려는 태그가 맞는지 확인하고 메소드를 적용시켜주는것이 좋음(nodeName)
The mechanism the JS interpreter uses to keep track of its place in a script that calls multiple functions. How JS "knows" what function is currently being run and what functions are called from within that function, etc.
HOW IT WORKS
when a script calls a function, the interpreter adds it to the call stack and then starts carrying out the function.
Any functions that are called by that function are added to the call stack further up, and run where their calls are reached
when the current function is finished, the interpreter takes it off the stack and resumes execution where it left off in the last code listing.
Ex)
const multiply = (x,y) => x*y;
const square = (x) => multiply(x,x);
const isRightTriangle = (a,b,c) => {
return square(a) + square(b) === square(c)
};
1)
2)
3)
4)
5)
console.log("Sending request to server!") - 1)
setTimeout(() => {console.log("Here is your data for the server...")}, 3000) - 2)
console.log("I AM AT THE END OF THE FILE!") -3)
1,2,3순서대로 출력을 해야할 것 같지만 JS는 1,3,2순서대로 출력
콜백함수: 파라미터로 함수를 전달하는 함수
콜백함수란 파라미터로 함수를 전달받아 함수의 '내부'에서 실행하는 함수이다.
//newcolor로 변신한다. delay를 두면서 그리고 (callback)함수를 실행한다.
const delayedColorChange = (newcolor, delay, callback) => {
setTimeout(() => {
document.body.style.backgroundColor = newcolor;
callback();
}, delay)
}
delayedColorChange('olive', 1000, () => {
delayedColorChange('blue', 1000, () => {
delayedColorChange('pink', 1000, () => {
delayedColorChange('magenta', 1000, () => {
delayedColorChange('green', 1000, () => {
})
})
})
})
});
//해당 함수가 실행될때/안될때를 나눠주기위한 콜백함수의 중첩
searchMoviesAPI('amadeus', () =>{
saveToMyDB(moveis, () => {
//if it works, run this
}, () =>{
//if it doesnt work, run this
})
}, () => {
//if API is down, or request failed
})
Enter Promises
A promise is an object representing the eventual completion or failure of an asynchornous operation.
A promise is a " returned object " to which you attach callbacks, instead of passing callbacks into a function.
// THE CALLBACK VERSION
const fakeRequestCallback = (url, success, failure) => {
const delay = Math.floor(Math.random() * 4500) + 500;
setTimeout(() => {
if (delay > 4000) {
failure('Connection Timeout :(')
} else {
success(`Here is your fake data from ${url}`)
}
}, delay)
}
// THE PROMISE VERSION
const fakeRequestPromise = (url) => {
return new Promise((resolve, reject) => {
const delay = Math.floor(Math.random() * (4500)) + 500;
setTimeout(() => {
if (delay > 4000) {
reject('Connection Timeout :(')
} else {
resolve(`Here is your fake data from ${url}`)
}
}, delay)
})
}
then/catch (then은 promise객체를 반환할 때 마다 불려지는 메소드)
// THE CLEANEST OPTION WITH THEN/CATCH
// RETURN A PROMISE FROM .THEN() CALLBACK SO WE CAN CHAIN!
fakeRequestPromise('yelp.com/api/coffee/page1')
.then((data) => {
console.log("IT WORKED!!!!!! (page1)")
console.log(data)
return fakeRequestPromise('yelp.com/api/coffee/page2')
})
.then((data) => {
console.log("IT WORKED!!!!!! (page2)")
console.log(data)
return fakeRequestPromise('yelp.com/api/coffee/page3')
})
.then((data) => {
console.log("IT WORKED!!!!!! (page3)")
console.log(data)
})
.catch((err) => {
console.log("OH NO, A REQUEST FAILED!!!")
console.log(err)
})
const fakeRequset = (url) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
},1000)
})
}
fakeRequset('/dogs/1')
.then(() => {
console.log("DONE WITH REQUEST !")
})
const fakeRequset = (url) => {
return new Promise((resolve, reject) => {
const rand = Math.random();
setTimeout(() => {
if(rand < 0.7) {
resolve("YOUR FAKE DATA HERE !");
} else {
reject('REQUEST ERROR !!');
}
},1000)
})
}
fakeRequset('/dogs/1')
.then((data) => {
console.log("DONE WITH REQUEST !")
console.log("data is: ", data )
})
.catch((err) => {
console.log("OH NO!", err)
})
//reject 은 필요없으니 기재 할 필요 없음
const changeNewColor = (newcolor,sec) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
document.body.style.bacgroundColor = newcolor
resolve();
}, sec)
})
}
changeNewColor('pink', 1000)
//changeNewColor함수가 실행되면 그 밑의 then 메소드 실행 그 다음 실행....
.then(() => changeNewColor('orange',1000))
.then(() => changeNewColor('olive',1000))
.then(() => changeNewColor('blue',1000))
.then(() => changeNewColor('green',1000))
Async Functions
함수 앞에 async를 입력해서 비동기 함수로 선언하면 자동으로 promise를 반환
async function hello() {
}
const sing = async() => {
return 'LA LAL LA'
}
const sing = async() => {
return 'LA LAL LA'
}
sing().then((data) => {
console.log("PROMISE RESOLVED WITH :" , data)
})
//오류를 던져서(throw) 실행한 promise
const sing = async() => {
throw "UH OH"
return 'LA LAL LA'
}
//오류를 던졌으므로 catch메소드가 실행됨.
sing()
.then((data) => {
})
.catch((err) => {
console.log("OH NO, PROMISE REJECTED")
console.log(err)
})
const login = async (username, password) => {
if(!username || !password) throw 'Missing Credentials'
if(password === 'abcd123!') return 'WELCOME!'
throw 'Invalid Password'
}
login('Tony')
.then((msg) => {
console.log("LOGGD IN !")
console.log(msg);
})
.catch((err) => {
console.log("ERROR!!!")
console.log(err);
})
const login = async (username, password) => {
if(!username || !password) throw 'Missing Credentials'
if(password === 'abcd123!') return 'WELCOME!'
throw 'Invalid Password'
}
//password 를 입력하지 않았을 때
login('Tony')
.then((msg) => {
console.log("LOGGD IN !")
console.log(msg);
})
.catch((err) => {
console.log("ERROR!!!")
console.log(err);
})
promise가 해결될 때까지 실행을 멈추는 키워드
const delayedColorChange = (color,delay) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
document.body.style.backgroundColor = color;
resolve();
}, delay);
})
}
delayedColorChange('red', 1000)
.then(() => delayedColorChange('orange',1000))
.then(() => delayedColorChange('yellow',1000))
.then(() => delayedColorChange('green',1000))
.then(() => delayedColorChange('blue',1000))
.then(() => delayedColorChange('indigo',1000))
.then(() => delayedColorChange('violet',1000))
async function rainbow() {
await delayedColorChange('red', 1000);
await delayedColorChange('orange', 1000);
await delayedColorChange('yellow', 1000);
await delayedColorChange('blue', 1000);
await delayedColorChange('indigo', 1000);
await delayedColorChange('violet', 1000);
}
async function makeTwoRequests() {
try {
let data1 = await fakeRequest('/page1');
console.log(data1)
let data2 = await fakeRequest('/page2');
console.log(data2)
} catch (err) {
console.log("CAUGHT AN ERROR!")
console.log9("error is: " , err)
}
}