this 키워드
- 메서드가 자신이 속한 객체의 프로퍼티를 참조하려면 먼저 자신이 속한 객체를 가리키는 식별자를 참조해야 함.
- 생성자 함수 내부에서는 프로퍼티 또는 메서드를 추가하기 위해 자신이 생성할 인스턴스를 참조해야 함.
this (자기 참조 변수)
- 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 특수한 식별자가 필요했다.
- 자바나 c++ 같은 클래스 기반 언어 : this는 언제나 클래스가 생성하는 인스턴스를 가리킴.
- 자바스크립트 : this는 함수가 호출되는 방식에 따라 this에 바인딩될 값이 결정됨.
- 전역에서 this는 전역 객체 window를 가리킴
- 일반 함수 내부에서는 전역 객체 window를 가리킴 (strict mode가 적용되면 undefined가 바인딩 됨.)
- 메서드 내부에서는 메서드를 호출할 객체를 가리킴
- 생성자 함수 내부에서는 생성자 함수가 생성할 인스턴스를 가리킴
함수 호출 방식과 this 바인딩
- 동일한 함수도 다양한 방식으로 호출할 수 있음
const foo = function() {
console.dir(this);
};
//1. 일반 함수 호출
foo(); //window
//2. 메서드 호출
const obj = {foo};
obj.foo(); //obj
//3. 생성자 함수 호출
new foo(); // foo{}
//4. Function.prototype.apply/call/bind 메서드에 의한 간접 호출
foo.call(bar);
foo.apply(bar);
foo.bind(bar)();
1. 일반 함수 호출
일반 함수로 호출된 모든 함수(중첩 함수, 콜백 함수 포함) 내부의 this는 전역 객체가 바인딩된다.
var value = 1;
const obj = {
value: 100,
foo() {
console.log("foo's this: ", this); {value:100, foo:f}
//콜백 함수 내부의 this에는 전역 객체가 바인딩됨.
setTimeout(function () {
console.log("callback's this :: ", this); //window
console.log("callback's this.value :: ", this.value); //1
}, 100);
}
};
obj.foo();
- 메서드 내부의 중첩 함수나 콜백 함수의 this 바인딩을 메서드의 this 바인딩과 일치시키기 위한 방법
->1) Function.prototype.apply, call, bind 메서드 활용
->2) 화살표 함수 활용
var value = 1;
const obj = {
value: 100,
foo() {
//bind 함수
console.log("foo's this: ", this); {value:100, foo:f}
setTimeout(function () {
console.log(this.value); //100
}.bind(this), 100);
//화살표 함수 내부의 this는 상위 스코프의 this를 가리킴
setTimeout(() => console.log(this.value), 100);
}
};
obj.foo();
2. apply, call, bind 메서드에 의한 간접 호출
- apply, call의 대표적인 용도 : arguments 객체와 같은 유사 배열 객체에 배열 메서드를 사용하는 경우
- arguments는 배열이 아니기 때문에 Array.prototype.slice와 같은 배열의 메서드를 사용하지 못하나 apply 나 call 메서드로 가능
function convertArgsToArray() {
console.log(arguments);
//arguments 객체를 배열로 변환
const arr = Array.prototype.slice.call(arguments);
console.log(arr);
return arr;
}
convertArgsToArray(1, 2, 3); // [1,2,3]
- bind 메서드는 apply와 bind와 달리 함수를 호출하지 않고,
첫 번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성해 반환
-> 메서드의 this와 메서드 내부의 중첩 함수 또는 콜백 함수의 this가 불일치하는 문제를 해결하기 위해 유용하게 사용됨.
function getThisBinding() {
return this;
}
const thisArg = { a:1 };
// bind 메서드는 첫번째 인수로 전달된 thisArg로 this 바인딩이 교체된 getThisBinding 함수를 새로 생성해 반환
console.log(getThisBinding.bind(thisArg)); // getThisBinding
// bind 메서드는 함수를 호출하지 않으므로 명시적으로 호출해줘야 함.
console.log(getThisBinding.bind(thisArg)()); // { a:1 }