221007.til

Universe·2022년 10월 7일
0

study

목록 보기
32/49

this

this 키워드를 쓰면 그 함수를 가지고 있는 오브젝트를 가리킨다. (전역에서는 window를 출력함)
addEventListener 안에서는 이벤트가 발생한 대상 을 가리킨다.

arrow function

특징 : 내부의 this 값을 변화시키지 않음. 외부의 this 값을 그대로 재사용할 수 있음.

function(){} 과 () ⇒ {} 의 차이로 알아보는 this

var object = {
        name: ["kim", "lee", "park"],
        func: function () {
          console.log(this);
          object.name.forEach(function () {
            console.log(this);
          });
        },
      };

      object.func();

var object = {
        name: ["kim", "lee", "park"],
        func: function () {
          console.log(this);
          object.name.forEach(() => {
            console.log(this);
          });
        },
      };

      object.func();

arrow function 는 외부의 this 값을 그대로 재사용 할 수 있으므로 편리하다.

arrow function

함수를 만드는 두가지 방법

  1. function()
var func = function() {
}

func();
  1. () ⇒
var func = () => {
}

func();

arrow function 의 장점
직관적이다. 파라미터가 1개면 소괄호를 생략할 수 있다.

var func = function(a){ return a+10 };
===
var func = a => a + 10;

사용예시

[1,2,3,4].forEach(function(a){
	console.log(a)
})
// 1,2,3,4

[1,2,3,4].forEach( a => console.log(a));
// 1,2,3,4

주의

arrow function 은 this 키워드를 재정의 해주지 않으므로
eventlistener 와 object 에서 사용할 때 주의해야 한다.

document.getElementById('button').addEventListener('click', (e) => {
		e.currentTarget !== this; // this가 window를 출력함

})
var obj = {
	func : () => {
		return this; // windows 를 출력함
	}
}

obj.func();

arrow function 은 eventlistener의 this 에서 제대로 활용할 수 있는 것 처럼 보인다.
다른 오브젝트나 function 안에서는 arrow function 을 사용한 this 를 사용하는 것 보다
e.currentTarget 이나 일반적인 함수선언을 하는게 좋겠다.
예시 한줄로 이해할 수 있는데,

document.querySelector(".button").addEventListener("click", function () {
        console.log(this);
        setTimeout(() => {
				// setTimeout(function() {
          console.log(this);
        }, 1000);
      });

eventListener 안의 this 함수는 이벤트 대상을 가리키게 되므로 버튼 요소를 가져온다.
그런데 콜백함수를 써야하는 setTimeout 같은 메소드를 사용할 때,
대상이 버튼을 가리키게 하고싶다면 arrow function 을 이용해서 상위요소의 this 값을 가져오면 되겠다.
위의 함수에서 이벤트리스너의 function 부분을 arrow function 으로 변경하면
마찬가지로 window 를 리턴하게 되니 주의.
복잡하고 햇갈리지만 정말 유용한 기능이다.

변수

let vs const

var 키워드를 대체해서 나온 문법.
변수에는 선언, 할당, 범위 라는 세가지 성격을 반드시 가지고 있는데,
javscript 의 변수 세가지는 각각 아래와 같은 특징을 가지고 있다.

var : 재선언 : O 재할당 : O 범위 : function
let : 재선언 : X 재할당 : O 범위 : { } (중괄호)
const : 재선언 : X 재할당 : X 범위 : { } (중괄호)

단, const 변수로 선언한 object 내의 key, value 값은 변경이 가능하다.
이마저도 수정이 불가능하게 만들고싶다면 object.freeze(obj) 라는 문법도 있다.
use strict 로 엄격모드까지 선언하면 에러메세지도 출력할 수 있다.

Hoisting

예를들어,

var name = 30;

라는 변수를 선언했다고 하면 자바스크립트에서는

<script>
var name;
...
name = 30;
</script>

이런식으로 변수의 선언을 변수 범위 최상단에 고정시켜놓고 지정위치에서 변수를 할당한다.

변수 여러개 만들기

var name='lee', age=20;

전역변수

모든 곳에서 쓸 수 있는 변수
습관적으로 script 최상단에 넣으면 전역으로 변수가 할당된다.
그런데,

window.name = 'kim'

이런식으로 window 에 할당하면 전역변수로 name 을 부를때마다 kim 을 출력받을 수 있다.
개발자들은 전역변수를 window 로 선언하는걸 지향한다고 한다.
좀 더 직관적이어서 그렇다는 것 같다.

간단한 문제로 알아보자 (함수표현식과 함수선언식의 차이)

			func();
      function func() {
        console.log(hello);
        let hello = "hi";
      }

      func2();
      var func2 = function () {
        console.log(hello);
        let hello = "hi";
      };

그냥봐도 총체적 난국인 이 두 함수를 어떤식으로 고칠 수 있을까 ?
우선 첫번째.
func 함수는 호이스팅되어 최상단에 위치하게 되므로 func() 가 함수선언보다 상단에 있어도
문제없이 작동된다.
물론 func 함수 안에 있는 let = hello 도 호이스팅이 된다.
그러나 호이스팅이 되는건 선언 부분.
값이 아직 할당되지 않았으므로 제대로 결과가 나오지 않는것이다.
var 로 변수를 선언하면 undefined 값이 자동으로 담겨 호이스팅이 되므로
에러를 출력하지 않고 undefined 값을 리턴하게 된다.
let 과 const 는 이러한 오류와 실수를 방지하기 위해 호이스팅시에 값을 할당하지 않는다.

			func();
      function func() {
				let hello = "hi";        
				console.log(hello);
      }

이런식으로 수정하면 되겠다.

두번째는 좀 더 난국이다.
비슷한 문제같지만

      func2();
      var func2 = function () {
        let hello = "hi";
        console.log(hello);
      };

Uncaught TypeError: func2 is not a function

func2 가 함수가 아니라는 에러가 뜬다.
왜그럴까 ?
자세히 보면 함수를 정의하는 방식에 차이가 있다.
첫번째 경우를 함수 선언식, 두번째의 경우를 함수 표현식 이라고 부르는데
함수 표현식은 호이스팅되지 않는다.
정확히는 함수 표현식의 선언부분, var func2; 부분만 호이스팅 된다.
함수 선언식은 함수의 전부가 호이스팅 된다.
var func2 가 정의되기 이전에는 var 로 변수를 선언했으므로 undefined 가 담겨있을테니
함수가 아니라는 에러가 뜨는것이다.

      var func2 = function () {
        let hello = "hi";
        console.log(hello);
      };
      func2();

이런식으로 고쳐주면 문제없이 작동한다.

반복문으로 알아보는 var 과 let (scope 개념)

<body>
<div style='display : none'>modal1</div>
<div style='display : none'>modal2</div>
<div style='display : none'>modal3</div>
<button>btn1</button>
<button>btn2</button>
<button>btn3</button>
</body>

<script>
var buttons = document.querySelectorAll('button');
var modals = document.querySelectorAll('modal');
for(var i=0; i < button.length; i++){
	buttons[i].addEventListener('click',function(){
		modals[i].style.display = 'block'
	})
}
</script>

//Uncaught TypeError: Cannot read properties of undefined (reading 'style')
    at HTMLButtonElement.<anonymous>

querySelectorAll 로 찾은 버튼을 클릭하면 모달을 활성화시켜주는 기능.
하지만 var 는 변수의 범위가 function 이라 전역으로 선언이 되어버린다.
실행순서 에 주의해서 보면 어떤 문제인지 잘 알 수 있다.
EventListenr 는 특정 이벤트가 발생했을 경우 실행되는데,
반복문은 이미 i++ 가 4번 실행이 됐기 때문에,
buttons[4], modals[4]를 찾으려고 하면 찾을 수 없는것이다.
따라서 변수의 범위가 중괄호인 let 으로 바꿔주면 정상적으로 작동한다.

이런 유효범위를 스코프(scope) 라고 하는데,
정확한 뜻으로는 자신이 선언된 위치에 따라 식별자 자신을 참조 가능한 유효범위 를 말한다.
식별자는 유일해야하지만 유효범위, 즉 스코프가 다르다면 중복이 가능하다.

let과 const 를 이러한 관점으로 바라볼 때,
코드 블록(if, while, for, function), 중괄호로 감싸진 영역의 스코프를 가진다.
var가 함수 레벨 스코프를 가지는 것과는 엄연하게 구분된다.

처음 자바스크립트를 배울 때 가급적이면 var를 사용하지 말라는 조언이 이러한 이유 때문이다.

profile
Always, we are friend 🧡

0개의 댓글