프론트엔드 데브코스 5기 TIL 12일차

타래·2023년 10월 4일
0
post-thumbnail

학습 내용


JS에서 this

JavaScript의 this는 함수가 어떻게 호출되었는지에 따라 달라집니다.

// 1. 전역 스코프
// 전역 스코프에서 this는 전역 객체를 참조합니다. 브라우저에서는 window 객체가 됩니다.
// (Node 환경에선 global, strict mode에서는 undefined.)
console.log(this === window); // true


// --------------------------------------------


// 2. 함수 호출:
// 일반 함수로서 호출될 때 this는 전역 객체를 참조합니다.
function func() {
  console.log(this);
}
func(); // window (브라우저에서)


// --------------------------------------------


// 3. 메서드 호출:
// 객체의 메서드로서 호출될 때 this는 해당 메서드를 호출한 객체를 참조합니다.
const myObj = {
  method: function() {
    console.log(this);
  	// this는 myObj를 가르킴.
  }
};
myObj.method(); 


// 3-1.
const myObj = {
  outerMethod: {
  	innerMethod: function(){
    	console.log(this);
	    // 이때 this는 outerMethod를 가르키게 됩니다.
    }
  }
};


// --------------------------------------------


// 4. 생성자 함수:
// new 키워드를 사용하여 생성자 함수를 호출하면, this는 새로 생성된 객체를 참조합니다.
function MyClass() {
  this.prop = "value";
}
const instance = new MyClass();
console.log(instance.prop); // "value"


// 4-1.
// 다만, new 생성자 함수 없이 함수를 호출하면, 에러가 발생합니다.
function MyClass() {
  this.prop = "value";
}
const instance = MyClass();
console.log(instance.prop); // TypeError: Cannot read properties of undefined

// a) MyClass 함수가 new 생성자 함수 없이 호출되었기에, 해당 함수 내부 this는 전역 window를 가르키게 됩니다.
// b) 또한 MyClass 함수는 리턴 값이 없으므로 instanc는 undefined 입니다.
//    때문에 출력문은 undefined.prop 이 되므로 TypeError를 출력하게 됩니다.


// --------------------------------------------


// 5. 화살표 함수:
// 화살표 함수는 자신만의 this 바인딩을 갖지 않습니다. 
// 때문에 상위 함수 scope를 찾아갑니다.

function OuterFunction() {
  this.value = "hello";
  
  this.arrowFunction = () => {
    console.log(this.value); // "hello"
  };
}

const instance = new OuterFunction();
instance.innerFunction(); 
instance.arrowFunction();


// --------------------------------------------


// 6. call, apply, bind:
// call, apply, bind 메서드를 사용하면 함수를 호출할 때 this의 값을 명시적으로 설정할 수 있습니다.
function showThis() {
  console.log(this);
}
const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };

showThis.call(obj1); // obj1
showThis.apply(obj2); // obj2

const boundFunction = showThis.bind(obj1);
boundFunction(); // obj1


// --------------------------------------------


// 7. 이벤트 핸들러:
// 대부분의 경우, 이벤트 핸들러에서 this는 이벤트를 발생시킨 DOM 요소를 참조합니다.


클로저

자주 보이는 예제인데, 헷갈리는 부분이 있었어서 다시 기록하려합니다.

for (var i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, i * 1000);
}
// 5, 5, 5, 5, 5
// var를 사용하면 for 루프의 반복마다 새로운 변수 인스턴스가 생성되지 않습니다. 
// 따라서 모든 setTimeout 콜백이 루프가 끝난 동일한 i 변수를 참조하게 됩니다.


for (let i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i);
  }, i * 1000);
}
// 0, 1, 2, 3, 4
// 각 setTimeout 콜백들이 for 루프의 각 반복에서의 새로운 i 인스턴스 값을 "캡처"했기에
// 스택 내부의 각 setTimeout들은 서로 다른 i 값을 참조하게 되었습니다.

// 물론 즉시실행함수(IIFE) 또는 forEach문을 사용해도 됩니다.

후기

아직 JS가 많이 부족하구나를 느꼈습니다. 더 꼼꼼히 열심히 공부해야겠어요.

0개의 댓글