8/9 ~ 13 복습

jiseong·2021년 8월 14일
0

T I Learned

목록 보기
32/291

오늘 한 일

✔️ 8/9 ~ 13 배운 내용 복습

새로배운 내용

  • ClassList toggle

요소에서 지정된 클래스를 제거하고 false를 반환한다.
클래스가 존재하지 않는 경우, 요소에 추가하고, 반환 값은 true

const buttons = document.querySelectorAll('button');

const handleClick = (btn) => {
    btn.classList.toggle('clicked');
}

[...buttons].map(button =>{
    button.addEventListener('click', (e) => handleClick(e.currentTarget));
})
#grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
    gap: 5px;
    padding: 5px;
    width: 300px;
    height: 300px;
}

button {
    cursor: pointer;
    background-color: #4290f5;
    transition: filter 0.9s;
}

button.clicked {
    background-color:#4242f5;
}

  • 동적 스코프(Dynamic scope)
    함수를 어디서 호출하였는지에 따라 상위 스코프를 결정하는 것
  • Arrow function의 this
    화살표 함수는 함수를 호출할 때가 아닌 선언할 때 this에 바인딩할 객체가 정적으로 결정된다.

    화살표 함수의 this는 언제나 상위 스코프의 this를 가리킨다. 이를 Lexical this라고 한다.

let user = {
    name: 'jiseong', 
    foo1: function() { 
	console.log(this); 
    },
    foo2: () => {
        console.log(this); 
    } 
} 
user.foo1(); // user
user.foo2(); // Window

위의 코드에서 메소드 foo2로 호출하여도 this가 window로 출력되는 것을 볼 수 있다. 이는 arrow function의 this선언할 때의 기준으로 상위 스코프 this를 가리키기 때문이다.

  • 클로저 활용 예시
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        const ul = document.createElement('ul');
        function funContext() {
          // var으로 선언된 for문
          for(var i = 0; i < 5; i++){

              const li = document.createElement('li');
              li.innerHTML = i;


              li.addEventListener('click', () => {
                  console.log(i);
              });


              ul.appendChild(li);
          }
        }
        funContext();
    
        document.body.appendChild(ul);  
    </script>

</body>
</html>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        const ul = document.createElement('ul');
        
      	function funContext() {
          // let으로 선언된 for문
          for(let i = 0; i < 5; i++){

              const li = document.createElement('li');
              li.innerHTML = i;


              li.addEventListener('click', () => {
                  console.log(i);
              });


              ul.appendChild(li);
          }
        }
        funContext();

        document.body.appendChild(ul);  
    </script>

</body>
</html>

위의 코드에서 i값이 콜백함수로 호출되어도 i값을 출력할 수 있는 이유는 클로저 덕분이다.
하지만 var로 선언했을 때는 항상 5로 나오지만
let으로 선언했을 때 제대로 된 값이 나오는 것을 볼 수 있다.
이를 이해하기 위해서는 실행 컨텍스트, 스코프, 호이스팅, 클로저 개념을 알고 있으면 좋다.

var로 선언했을 때는
var는 함수레벨 스코프로 호이스팅이 일어나면서 funContext의 최상단으로 가기 때문이고 Lexical Environment에는 Var 변수가 존재 할 수 없으니 스코프 체인을 통해 i 값을 찾는다. 따라서 최종 결과 값인 5가 나오게 되는 것이다.

for(var j = 0; j< 2; j++){
}
console.log(j); // 3

let으로 만든 변수는 블록레벨 스코프로 새로운 Lexical Environment이 생기면서 그 안에 존재하기 때문에 각자의 값을 가질 수 있어 원하는 결과를 가질 수 있었다.

Lexical Environment에는 let, const로 선언된 변수가 존재
Variable Environment에 var로 선언된 변수 존재가 존재
이때, 블록 코드는 Lxical Environment만 생성한다고 한다.

Reference

0개의 댓글