상황에 따라 달라지는 this함수 vs 메서드메서드 내부에서의 this함수 내부에서의 this콜백 함수 호출 시 그 함수 내부에서의 this생성자 함수 내부에서의 this명시적으로 this를 바인딩하는 방법call 메서드apply 메서드bind 메서드별도의 인자로 this를 받는 경우(콜백 함수 내에서의 this)
상황에 따라 달라지는 this
- 자바스크립트에서
this
는 기본적으로 실행 컨텍스트가 생성될 때 함께 결정됨
- 실행컨텍스트는 함수를 호출할 때 생성 되므로 바꿔 말하면
this
는 함수를 호출할 때 결정된다고 할 수 있음
함수 vs 메서드
var func = function (x) { console.log(this, x); }; func(1); // Window { ... } 1 var obj = { method: func }; obj.method(2); // { method : f } 2 obj['method'](2); // { method : f } 2
func
로 호출 시에는this
가 전역객체Window
obj.method
로 호출 시에는this
가obj
- 함수는 그 자체로 독립적인 기능을 수행하는 반면, 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행함
메서드 내부에서의 this
- this에는 호출한 주체에 대한 정보가 담김
- 어떤 함수를 메서드로서 호출하는 경우 호출 주체는 바로 함수명(프로퍼티명) 앞의 객체임
함수 내부에서의 this
- 어떤 함수를 함수로서 호출할 경우에는 this가 지정되지 않음
this에는 호출한 주체에 대한 정보가 담긴다
고 했는데, 함수로서 호출하게 되면 호출 주체를 명시하지 않고 개발자가 직접 실행한 것이기 때문에 호출 주체의 정보를 알 수가 없음
콜백 함수 호출 시 그 함수 내부에서의 this
setTimeout(function () { console.log(this); }, 300); // 전역객체 출력 [1, 2, 3, 4, 5].forEach(function (x) { console.log(this, x); // 전역객체 }); document.body.innerHTML += '<button id="a">클릭</button>'; document.body.querySelector('#a') .addEventListener('click', function (e) { console.log(this, e); // 위에 지정한 엘리먼트를 출력 });
addEventListener
메서드는 콜백 함수 호출 시 자신의this
를 상속하도록 정의되어 있어서 엘리먼트를 출력
- 나머지 메서드는 콜백함수 호출 시 대상이 될
this
를 지정하지 않기에 전역객체를 출력
생성자 함수 내부에서의 this
var Cat = function (name, age) { this.bark = '야옹'; this.name = name; this.age = age; }; var choco = new Cat('초코', 7); var nabi = new Cat('나비', 5); console.log(choco, nabi); /* Cat { bark: '야옹', name: '초코', age: 7 } Cat { bark: '야옹', name: '나비', age: 5 } */
명시적으로 this를 바인딩하는 방법
call 메서드
Function.prototype.call(thisArg[, arg1[, arg2[, ...]]])
call
메서드는 메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령
call
메서드의 첫 번째 인자를this
로 바인딩하고, 이후의 인자들을 호출할 함수의 매개변수로 넘겨줌
- 함수를 그냥 실행하면
this
는 전역객체를 참조하지만call
메서드를 이용하면 임의의 객체를this
로 지정할 수 있음
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])
- apply 메서드는 call 메서드와 기능적으로 완전히 동일함
- call 메서드는 첫 번째 인자를 제외한 나머지 모든 인자들을 호출할 함수의 매개변수로 지정,
- apply 메서드는 두 번째 인자를 배열로 받아 그 배열의 요소들을 호출할 함수의 매개변수로 지정한다는 점에서 차이가 있음
var func = function (a, b, c) { console.log(this, a, b, c); }; func.apply({x:1}, [4, 5, 6]);
bind 메서드
Function.prototype.bind(thisArg[, arg1[, arg2[, ...]]])
bind
메서드는 ES5에서 추가된 기능으로,call
과 비슷하지만 즉시 호출하지는 않고 넘겨 받은this
및 인수들을 바탕으로 새로운 함수를 반환하기만 하는 메서드임
var func = function (a, b, c, d) { console.log(this, a, b, c, d); }; func(1,2,3,4); // Window{ ... } 1 2 3 4 var bindFunc1 = func.bind({ x: 1}); bindFunc1(5, 6, 7, 8); // {x : 1 } 5 6 7 8 var bindFunc2 = func.bind({ x: 1}, 4, 5); bindFunc2(6, 7); // { x : 1 } 4 5 6 7 bindFunc2(8, 9); // { x : 1 } 4 5 8 9
별도의 인자로 this를 받는 경우(콜백 함수 내에서의 this)
- 콜백 함수를 인자로 받는 메서드 중 일부는 추가로
this
로 지정할 객체(thisArg
)를 인자로 지정할 수 있는 경우가 있음
- 이러한 메서드의
thisArg
값을 지정하면 콜백 함수 내부에서this
값을 원하는 대로 변경할 수 있음
Array.prototype.forEach(callback[, thisArg]); Array.prototype.map(callback[, thisArg]); Array.prototype.filter(callback[, thisArg]); Set.prototype.forEach(callback[, thisArg]); Map.prototype.forEach(callback[, thisArg]);