this
는 자신을 호출한 객체, 자신이 생성할 객체
이 두 경우 객체를 가리키는 자기 참조변수.
this
는 함수가 만들어질 때가 아닌 '실행'될 때 그 값이 결정된다.
상황별로 호출 방법이 다양하다.
일반적인 함수 호출에서 this
는 전역 객체인 window
(node는 global)를 가리킨다.
function a(){
console.log(this)
}
a()
//Window {0: Window, 1: global, window: Window, self: Window, document: document, name: '', location: Location, …}
//undefined
전역공간에 선언하는 함수는 전역공간을 가리킨다. 메서드호출이 아닌 a()
함수를 직접 호출하여 함수의 컨텍스트가 어디 속하는지 알 수 없기 때문에 undefined
를 출력한다.
메서드로 호출한 경우 this
는 멤버접근연산자 앞의 객체를 가리킨다.
메서드를 어떻게 호출했냐에 따라 this
바인딩이 달라진다.
const obj = {
val: 100,
func: function() {
console.log(this) //obj객체를 가리킴
}
}
obj.func()
생성자 함수 내에서 this
는 새로 생성되는 인스턴스 객체를 가리킨다.
생성자 함수를 사용하면 공통된 속성과 메서드를 가진 객체들을 쉽게 생성하고 관리할 수 있다. 이런 과정은 new
키워드와 생성자함수를 호출한 경우에만 실행된다.
function Person(name, age) {
this.name = name; //객체를 생성하고 초기화 한다
this.age = age;
}
// 생성자 함수 호출
const person1 = new Person('Alice', 30);
const person2 = new Person('Bob', 25);
console.log(person1); // { name: 'Alice', age: 30 }
console.log(person2); // { name: 'Bob', age: 25 }
이 세가지 함수를 사용하여 this
값을 수동으로 설정할 수 있다.
첫번째 인자로 this
로 바인딩할 객체를 지정한다.
peter객체를 call()
의 인자로 넘겨 bruce 객체가 this로 바인딩.
sayName()
함수 내에서 this.name
을 통해 bruce 객체의 name 프로퍼티에 접근할 수 있게 된다.
var peter = {
name : 'Peter Parker',
sayName : function(){
console.log(this.name);
}
}
var bruce = {
name : 'Bruce Wayne',
}
peter.sayName.call(bruce);
//Bruce Wayne
call()
와 동일하지만, 호출하는 함수에 전달할 인자들을 배열형태로 전달해야 한다.
const obj = {name: 'Lee'}
function user(age,country) {
return `name: ${this.name}, age: ${age}, country: ${country}`
}
console.log(user.apply(obj, [20,'korea']))
//name: Lee, age: 20, country: korea
bind()는 this 값을 고정시키는 메서드로 함수를 호출할 때 함수 내부에서 this가 어떤 객체를 가리킬지를 명시적으로 지정할 수 있도록 도와준다. 이를 통해 함수를 나중에 호출할 때 this 값이 항상 고정된다.
this
를 바인딩하여 함수를 호출하지않고, 새로운 함수를 반환한다.
const person = {
firstName: "Zanmang",
lastName: "loopy",
getFullName: function() {
return this.firstName + " " + this.lastName;
}
};
const printFullName = person.getFullName;
console.log(printFullName()); // 결과: undefined undefined
const boundPrintFullName = printFullName.bind(person);
console.log(boundPrintFullName()); // 결과: Zanmang loopy
bind()
를 사용하여 person.getFullName 함수의 this 값을 person 객체로 고정시킨 새로운 함수를 생성하면, 해당 함수를 호출할 때 this가 항상 person 객체를 가리킨다.
화살표 함수 내에서 this
는 함수를 둘러싼 스코프의 this
를 그대로 가져온다.
즉, 화살표 함수 내에서의 this
는 함수를 정의할 때의 컨텍스트를 유지한다.
화살표 함수의 경우 상위 스코프의 this를 가리킨다(Lexical this)
// a에서 this = person
// b에서 this = 상위스코프(상위에서 person을 보고있음) 즉 person
// c에서 this = 상위스코프(상위에서 person을 보고있음) 즉 person
const person = {
name: 'Loopy',
age: 25,
a(){
console.log(this);
console.log(this.name);
let b = () => {
console.log(this);
console.log(this.name);
let c = () => {
console.log(this);
console.log(this.name);
}
c()
}
b()
}
}
person.a()
//출력
{name: 'Loopy', age: 25, a: ƒ}
Loopy
{name: 'Loopy', age: 25, a: ƒ}
Loopy
{name: 'Loopy', age: 25, a: ƒ}
Loopy
이런 특징으로 화살표함수의 this
는 생성자 함수, call()
,apply()
,bind()
함수를 사용하여 변경할 수 없다. 아래 코드처럼 call()
을 사용해도 화살표함수의 this
는 변경되지 않고, 전역객체를 가리킨다.
this 를 쓰는 이유?
this
를 통해 코드를 더 유연하고, 재사용 가능하다.- 객체의 메서드 내에서 해당 객체의 속성과 메서드에 접근하기 위해 사용한다.
- 생성자 함수를 사용하여 새로운 인스턴스 객체를 생성, 초기화한다.
- 이벤트 핸들러 함수 내에서 이벤트가 발생한 요소와 관련된 작업을 처리한다.
- 화살표 함수를 사용하여 스코프 내의
this
값을 유지하고 코드를 간결하게 작성한다.
유익한 글이었습니다.