HTML/CSS의 지식을 다시 견고히 다지겠다고 마음먹은 후 CSS의 position쪽 공부를 하다가 갑자기 도형을 그리고 싶어졌다.
도형을 하나 그려본다.
//style
#wrapper{
border: 1px solid black;
width: 100px;
height: 100px;
position: absolute;
}
//html
<div id="wrapper">
<div id="wrapper" onclick=onClick()>
</div>
멋있는 사각형이 완성되었다. ㅋ
absolute를 배우고 있었으므로 내가 그리고자 하는 도형은 곂곂이 쌓인 사각형 5개를 그려보는 것.
이렇게 더 멋있는 사각형이 되었다. ㅋ
사실 삼항연산자 너무 대강 썼는데 핵심은 이게 아니니..
간단한 설명을 한 뒤 핵심으로 들어가겠다.
onClick = () =>{
for(let i = 1 ; i< 5; i++){
setTimeout(function(){
const wrapper =document.getElementById('wrapper')
const createDiv = document.createElement('div')
const color=
['red','blue','black','pink','red','blue','black','pink']
createDiv.style= `border: 1px solid black;
background-color:
${color[Math.floor(Math.random()*10)] ?
color[Math.floor(Math.random()*10)]: color[0] };
width: 100px;
height: 100px;
position: absolute;
margin:${i*20}px`
wrapper.appendChild(createDiv)
},1000 * i)
}
}
for문을 생성 (사각형 몇 개 그릴래?) -> 5개
그 후 setTimeout을 적용해, 한번에 5개가 짠 하고 나타나지 않고, 1초,2초....뒤에 하나씩 나오게끔 구현(중요한 내용이라 밑에 다시 다룰예정)
저 사각형의 부모요소에 접근 후, div element생성.
div의 스타일에 대한 접근 -> 크기, 높이, 같은 정적인 요소들 생성 + margin과 color에는 동적인 접근
대충 사각형 다 만들었고, 이제 appendChild 말 그대로 자식을 넣겠다.=> wrapper안에 createDiv를 넣음. (div>div 구조)
이렇게 실행을 해보면 1,2... 5초동안 5개의 사각형이 그려진다.
처음 이 사각형을 만들 때, for문 안에 setTimeout을 쓴다는 것에 대해 별 생각이 없다가 꽤나 난항을 겪을뻔 했다. 분명 내가 알고있는 사실인데..
이것에 대한 설명은 너무나 많은 곳에서 했기 때문에, 간단하게 코드로만 작성
// var i = 1;
for(i=1; i<6; i++){
console.log(i)
setTimeout(function(){
console.log(i)
document.write(i);
}, 1000* i);
}
console.log(i)
함수레벨의 스코프인 var는 최종적으로 1이 아닌 6이 출력된다는 사실을 알고있다.
그러면 저 비동기함수인 setTimeout에서는 어떻게 동작될까?
https://velog.io/@kip/JS-ConfEUWhat-the-heck-is-the-event-loop-part.2
(나름 잘 정리된 나의 글..)
for문은 분명 stack에 쌓일거고 비동기에는 setTimeout이 동작 중일 것이다.
우리가 상상한 계획은 123456이다. 그런데 HTML에서는 666666을 그린다.
여차하면 666666을 위해서 만들었다고 뻥치자
방법이 여러가지가 있다.
그냥 for문 초기화문에 let을 쓰고 전역에서 var를 지운다. 깔끔하게ㅎ
(공부를 위해서는 이런 우회법으로 돌아가면 하나를 놓칠 가능성이 있다.)
클로저
두두두둥장.
클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다.
클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지
(Lexical scoping)를 먼저 이해해야 한다.
진짜 간단한 함수 하나로 보자. (모질라에서 긁어왔다)
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
}
반복문을 heplText의 길이(3)만큼 돌린다. -> var item = helpText[0->1->2]가 된다. (자동)
onfocus는 내가 마우스를 클릭할 때 실행된다. (수동)
여기서부터 뭔가 이상하다. 그럼 내가 클릭할 때면? var item = helpText[2] 가 값으로 들어간다.
우리가 생각한건..
your e-mail address
가 뜨겠구만? -> 아냐 돌아가. you must be over 16
your full name
이 뜨겠구만? -> 어림도 없어 you must be over 16
해결책(나에게 let이 없다는 가정을 하자 때는 ES2015 전..)
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
function makeHelpCallback(help) { <----이녀석의 추가
return func![](https://velog.velcdn.com/images/kip/post/e69b6d98-db27-41eb-8abd-2758ed977d24/image.png)
ion() {
showHelp(help);
};
}
for (var i = 0; i < helpText.length; i++) {
var item = helpText[i];
document.getElementById(item.id).onfocus =
makeHelpCallback(item.help) <-- cb
}
}
function showHelp(help) {
document.getElementById('help').innerHTML = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
for (var i = 0; i < helpText.length; i++) {
(function() {
var item = helpText[i];
document.getElementById(item.id).onfocus = function() {
showHelp(item.help);
}
})(); // Immediate event listener attachment with the current value of item (preserved until iteration).
}
}