[JavaScript] this

ayboori·2024년 12월 2일

Nest.js

목록 보기
9/11
post-thumbnail

다른 대부분의 객체지향 언어에서 this는 클래스로 생성한 인스턴스 객체를 의미한다.

자바스크립트에서 this는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정된다.
즉, this는 함수를 호출할 때 결정된다. 함수가 호출되는 방식에 따라 this가 달라진다.

누가 나를 불렀느냐

전역 공간에서의 this

  • 전역 객체
    브라우저 공간에서는 window / Node.js 환경에서는 global

메서드로서 호출 시 메서드 내에서의 this

함수 vs 메서드

  • 함수 : 그 자체로 독립적인 기능을 수행한다.
  • 메서드 : 자신을 호출한 대상 객체에 대한 동작을 수행한다.
    (객체의 프로퍼티에 할당된 함수로서 호출될 경우 메서드로 동작한다)

같은 함수에서this를 리턴하도록 하더라도 전역 변수에서 호출 시 window를, 특정 객체의 프로퍼티에 할당 후 obj.method(); 혹은 obj['method'](); 로 호출 시 method를 호출한다.

함수를 메서드로서 호출 시 this의 호출 주체

  • 함수명 바로 앞의 객체

var obj = {
  	methodA : function() { console.log(this); },
  	inner : {
      	methodB : function() { console.log(this); }
    }
}

obj.methodA(); // == obj

obj.inner.methodB(); // == obj.inner

함수로서 호출 시 함수 내에서의 this

this가 지정되지 않으므로 전역 객체를 가리킨다.

객체 내에서만 생성된 함수더라도, onj.inner(); 이런 식으로 객체로서 호출된 게 아닌 inner()로 호출되었다면 함수로서 호출된 것이므로 window를 리턴한다.

즉, 함수 실행 당시 주변 환경 (메서드 내부인지, 함수 내부인지 등)은 중요하지 않고, 함수 호출 구문 앞의 . 이나 [] 가 있는지가 관건이다.

주변 환경에 구애 받게 하고 싶을 때

  1. 변수를 활용한다.
// 객체 내부

var self = this;
var innerfunc = function(){
	console.log(self); // 객체 리턴 
};

innerfunc();
  1. this를 바인딩하지 않는 함수 화살표 함수
// 객체 (obj) 내의 메소드 (outer) 내에 선언

var innerFunc = () =>{
  	console.log(this); // 메소드를 리턴 (outer: f)
};

innerFunc();
  1. call / apply / bind
  • 뒤에서 설명

콜백 함수 호출 시 그 함수 내부에서의 this

// 콜백 함수 호출 시 대상이 될 this를 지정하지 않음
setTimeout(function() { console.log(this); }, 300);

// 콜백 함수 호출 시 대상이 될 this를 지정하지 않음
[1,2,3,4,5].foreach(function (x) {
  console.log(this.x);
});

// 지정한 HTML 엘리먼트에 'click' 이벤트 발생 시마다 실행
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a') // 위의 element를 지정
	.addEventListner('click', fuction(e){ // 클릭 시 콜백 함수
    	console.log(this,e); // element와 함께 this 출력
	});

앞의 두 함수는 this를 지정하지 않았기 때문에 전역객체를 참조한다.
addEventListener 메서드는 콜백 함수를 호출할 때 자신의 this를 상속하도록 정의되어 있다.

콜백 함수의 제어권을 가지는 함수가 콜백 함수에서의 this를 무엇으로 할지를 결정한다.
특별히 정의되지 않은 경우 기본적으로 전역객체를 바라본다.

생성자 함수 내부에서의 this

자바스크립트의 경우 함수 호출 시 new 명령어와 함께 호출하면 해당 함수가 생성자로서 동작한다.
어떤 함수가 생성자 함수로서 호출된 경우 내부에서의 this는 곧 새로 만들 구체적인 인스턴스 자신이 된다.

class Polygon {
  constructor(name) {
    this.name = name; // 여기서의 this는 각각 poly1, poly2가 된다.
  }
}

const poly1 = new Polygon("One");
const poly2 = new Polygon("Two");

console.log(poly1, poly2);
// 결과
// Polygon { name : "One" }
// Polygon { name : "Two" }

명시적으로 this를 바인딩하는 방법

앞 절의 규칙을 깨고 별도의 대상을 바인딩할 수 있다.
this를 바꿔 어떤 함수가 어느 객체 안에 있도록 할 수 있다.

https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-Call-Bind-Apply

call 메서드

메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령이다.
메서드에 대해서도 마찬가지로 임의의 객체를 this로 지정할 수 있다.

Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])

첫 번째 인자를 this로 바인딩 / 나머지 인자는 fuction의 매개 변수로 한다.

var func = function (a,b,c){
  	console.log(this,a,b,c);
};

func(1,2,3); // 기본적으로 전역 객체 / Window{ ...} 1 2 3
func.call({x: 1}, 4,5,6} // {x:1} 4 5 6

apply 메서드

Function.prototype.apply(thisArg[, argsArray])
call 메서드와 기능적으로 완전히 동일하다.
차이점은 Function의 매개변수를 배열로 받는다는 것이다.

var func = function (a,b,c){
  	console.log(this,a,b,c);
};

func(1,2,3); // 기본적으로 전역 객체 / Window{ ...} 1 2 3
func.apply({x: 1}, [4,5,6]} // {x:1} 4 5 6
          

call, apply의 활용

유사 배열 객체에서 배열 메소드를 사용하기

https://velog.io/@onezerokang/%EC%9C%A0%EC%82%AC-%EB%B0%B0%EC%97%B4-%EA%B0%9D%EC%B2%B4%EC%99%80-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%B0%A8%EC%9D%B4

유사 객체 배열 : 배열처럼 보이지만 key는 숫자이고, length 값을 가진 객체를 말한다.

{
  0: div.text,
  1: div.text,
  2: div.text,
  3: div.text,
  length: 4,
}

Array.prototype.배열메서드.call(obj,'d');
: 배열의 프로토타입에 있는 배열 메서드를 빌려 쓰는 것이다.
: 리턴 값이 배열로 정해진 메서드가 아니라면, 얕은 복사 수행 없이 배열의 메서드를 활용할 수 있다.

유사 배열 객체에서 배열 메소드를 사용하기 - Array.from

https://velog.io/@onezerokang/%EC%9C%A0%EC%82%AC-%EB%B0%B0%EC%97%B4-%EA%B0%9D%EC%B2%B4%EC%99%80-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%B0%A8%EC%9D%B4

생성자 내부에서 다른 생성자를 호출

A객체 내부의 생성자에서
B객체.call(this,매개변수1,매개변수2,..);
를 수행하여 다른 객체의 속성을 정의할 수 있다.

여러 인수를 묶어 하나의 배열로 전달 - apply / 펼치기 연산자

객체나 배열의 값을 하나씩 꺼내어 연산한다.

  • array1.push(array2); : array1 뒤에 array2 배열 자체가 들어가 2차원 배열이 된다.
[1,2,3,[4,5]]
  • Array.prototype.push.apply(arr1, arr2); : array2의 값을 꺼내어 붙인다.
[1,2,3,4,5]

bind 메서드

Function.prototype.bind(thisArg [,arg1[, arg2, ...]]])

  • call 메서드와 비슷하지만 메서드를 즉시 호출하지 않고, 새롭게 생성된 함수 자체를 반환한다.
    - 새로운 함수는 bound 라는 호칭이 붙는다. (ex. func -> bound func)
  • 부분 적용 함수 : 호출하려는 메서드의 모든 인수를 넣지 않고 bind 메서드를 선언하고, 여기서 생성한 새로운 함수를 호출할 때 나머지 인수를 넣을 수 있다.

상위 컨텍스트의 this를 내부 함수 / 콜백 함수에 전달

상위 컨텍스트 내 / 내부 함수 외부에서 call, bind 등을 호출하면 상위 컨텍스트의 this를 전달한다.

// obj 객체 내의 outer 함수

var innerFunc = function() {
  console.log(this); 
};
innerFunc.call(this); // or apply - // 여기서 this는 obj
// obj 객체 내의 outer 함수

var innerFunc = function() {
  console.log(this); 
}.bind(this); // 여기서 this는 obj

화살표 함수

https://ko.javascript.info/arrow-functions-basics

this를 바인딩하지 않는 함수

// 객체 (obj) 내의 메소드 (outer) 내에 선언

var innerFunc = () =>{
  	console.log(this); // outer
};

innerFunc();
  • 화살표 함수 내부에는 this가 아예 없고, 접근하고자 하면 스코프체인상 가장 가까운 this에 접근한다.
    선언 당시의 스코프에서의 this를 상속받는다.

https://nykim.work/71
profile
프로 개발자가 되기 위해 뚜벅뚜벅.. 뚜벅초

0개의 댓글