2차 공부/TIL

24.07.23 This

공대탈출 2024. 7. 23. 17:49

this는 실행 컨텍스트가 생성될 때 결정된다. 이것을 this를 bind한다라고 한다.

 

전역공간에서의 this는 전역 객체를 가리킨다.
this에는 호출을 누가했는지에 대한 정보가 담긴다.

브라우저에서의 this === window
node에서의 this === global

 

 

함수에서의 this, 메서드에서의 this

함수와 메서드는 비슷해보이지만 '독립성'에서 차이가 있다.

함수는 그 자체로 기능을 수행하지만, 메서드는 호출당한 객체에 대한 동작을 수행한다.

함수()
객체.메서드()

 

var func = function (x) {
    console.log(this, x);
};
func(1);

var obj = {
    method: func,
};
obj.method(2);

함수자체에서의 this는 전역객체를 의미함을 알 수 있다.

 

 

메서드 내부에서의 this

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

obj.methodA();             // this === obj
obj['methodA']();          // this === obj

obj.inner.methodB();       // this === obj.inner
obj.inner['methodB']();    // this === obj.inner
obj['inner'].methodB();    // this === obj.inner
obj['inner']['methodB'](); // this === obj.inner

 

함수는 앞에서 말했듯이 독립적이기 때문에 함수 내부에서의 this는 지정되지 않는다.

함수 내부에서의 this

  • 어떤 함수를 함수로서 호출할 경우 this는 지정되지 않는다. (호출 주체를 알 수 없기 때문에)
  • 실행 컨텍스트를 활성화할 당시 this가 지정되지 않은 경우, this는 전역 객체를 의미한다.
  • 따라서 함수로서 '독립적'으로 호출할 때는 this는 항상 전역객체를 가리킨다.

 

메서드의 내부함수에서의 this

메서드는 호출 주체가 있고 함수는 호출 주체가 없으므로 메서드 내부함수의 this도 전역객체를 가리킨다.

var obj1 = {
    outer: function () {
        console.log(this); // (1)
        var innerFunc = function () {
            console.log(this); // (2)
        };
        innerFunc();	// (2)

        var obj2 = {
            innerMethod: innerFunc,
        };
        obj2.innerMethod();	// (3)
    },
};
obj1.outer();	//(1), (2)

1에서 메서드로서의 this 호출, 2에서 함수로서의 this 호출, 3에서 메서드로서의 this 호출을 하였기 때문에 위와 같은 결과가 나온다.


메서드의 내부함수에서 this 우회

var obj1 = {
    outer: function () {
        console.log(this); // (1) outer

        // AS-IS : 기존
        var innerFunc1 = function () {
            console.log(this); // (2) 전역객체
        };
        innerFunc1();

        // TO-BE : 이후
        var self = this;
        var innerFunc2 = function () {
            console.log(self); // (3) outer
        };
        innerFunc2();
    },
};

// 메서드 호출 부분
obj1.outer();

변수에 this를 미리 저장해두어 우회한 모습을 볼 수 있다.

 

var obj = {
    outer: function () {
        console.log(this); // (1) obj
        var innerFunc = () => {
            console.log(this); // (2) obj
        };
        innerFunc();
    },
};

obj.outer();

화살표 함수를 사용해서도 this를 우회할 수 있다.

일반함수에서의 this는 함수 그 자체를 의미하지만, ES6에서 추가된 화살표함수는 this를 outer로 잡기 때문에 this를 사진과 같이 출력해주는 것을 볼 수 있다.


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

// 별도 지정 없음 : 전역객체
setTimeout(function () { console.log(this) }, 300);

// 별도 지정 없음 : 전역객체
[1, 2, 3, 4, 5].forEach(function(x) {
	console.log(this, x);
});

// addListener 안에서의 this는 항상 호출한 주체의 element를 return하도록 설계되었음
// 따라서 this는 button을 의미함
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function(e) {
	console.log(this, e);
});

콜백함수도 함수이기때문에 this를 전역 객체를 참조하지만, addEventListener는 만들어 질 때 호출한 주체의 element를 가리킨다.

따라서 위 코드에서 eventListener의 콜백함수에서의 this는 해당 버튼을 가리킨다.


명시적 this binding

//명시적 this binding
// call, apply, bind
// call
var func = function (a, b, c) {
    console.log(this, a, b, c);
};

// no binding
func(1, 2, 3); // Window{ ... } 1 2 3

// 명시적 binding
func.call({ x: 1 }, 4, 5, 6);

 

 

var obj = {
    a: 1,
    method: function (x, y) {
        console.log(this.a, x, y);
    },
};

obj.method(2, 3); // 1 2 3
obj.method.call({ a: 4 }, 5, 6); // 4 5 6

MDN - call()

 

 

 

 

// //명시적 this binding
// // call, apply, bind
// // call
var func = function (a, b, c) {
    console.log(this, a, b, c);
};

func.apply({ x: 1 }, [4, 5, 6]);

var obj = {
    a: 1,
    method: function (x, y) {
        console.log(this.a, x, y);
    },
};

obj.method.apply({ a: 1 }, [7, 8]);

 

MDN - apply()

 

call()과 apply()는 사용방식이 조금 다를 뿐 같은 기능을 수행한다.