그룹스터디 🦆 팀 러버덕과 함께!
< 목차 >
1.this란?
2.함수 호출 방식과 this 바인딩
-1.일반 함수 호출
-2.메서드 호출
-3.생성자 함수 호출
-4.Function.prototype.apply / call/ bind로 호출
3.화살표 함수에서의 this
4.정리
this는 생성된 객체인 자기 자신을 가리킨다.
즉, 자신이 속해있는 객체를 가리키는 키워드다.
만약 생성된 객체 이름이 'apple'이라면 this는 apple이다.
객체 이름이 'apple'에서 'banna'로 바꾸더라도 this를 쓰면 banna를 가리킨다.
바뀐 객체이름 상관없이 this는 자신이 속한 객체를 가리킨다.
this도 함수 호출에 따라서 this가 가리키는 값이 다르다.
그리고 바인딩이란, this를 특정객체에 묶어 주는 것을 말한다.
예를 들면, 일반함수에서 this는 글로벌 객체와 묶이게 되고
메서드안의 this는 메서드를 가지고 있는 객체를 가리킨다.
1️⃣ 일반 함수안에서 this는 글로벌 객체와 바인딩 된다.
function apple(){
console.log(this);// Window{...}
console.log(this===window);// true;
}
2️⃣ 일반 함수내부 함수의 this도 글로벌 객체와 바인딩 된다.
function apple(){
function inner(){
console.log(this); // Window{...}
console.log(this === window); // true;
}
inner();
}
3️⃣ 메서드 내의 일반 함수 this도 글로벌 객체와 바인딩 된다.
const apple= {
getFruit(){
function banna(){
console.log(this); // Window {...}
console.log(this=== window); //true
}
banna();
}
}
apple.getFruit();
메서드의 this는 메서드를 호출한 객체와 바인딩 된다.
this에 바인딩 될 객체는 메서드가 호출되는 시점에 결정된다.
const fruit= {
name:"apple",
color:'red',
fruitName : function(){
console.log(this); // {name: 'apple', color: 'red', fruitName: ƒ, fruitColor: ƒ}
console.log(this.name); //apple
}
}
fruit.fruitName(); 메서드 호출한 fruit에 this바인딩
생성자 함수의 this는 생성자 함수로 만들어지는 인스턴스에 바인딩 된다.
function Person(name) {
console.log(this); Person{}
this.name = name;
console.log(this); Person{name: 'sally'}
}
const sally = new Person("sally");
생성자 함수가 실행 전, this는 빈 객체를 가리키고 인스턴스를 생성하고 나면 this는 이제 인스턴스에 바인딩 되어서 this.name이 인스턴스가 넘겨준 값을 가리키는 것을 볼 수 있다.
apply,call,bind는 Prototype에 존재하는 메서드로 모든 함수들이 상속받아서 사용할 수 있다.
apply와 call은 특정 객체를 자신과 묶어준다. 그래서 this의 값은 특정 객체를 가리키게된다.
function color(){
console.log(this);
}
const bright = {name:'skyblue'};
✨ call로하든 apply로하든 이제 color함수는 color객체와 묶여졌으므로
✨ color함수의 this는 글로벌 객체가 아닌 bright객체를 가리킴
color.call(bright); // {name: 'skyblue'}
color.apply(bright); // {name: 'skyblue'}
하지만 여기서 apply와 call의 차이점은,
call은 그냥 인자를 여러개 전달할 수 있지만, apply는 배열형태로 인자를 전달해야한다는 것이다.다만, 배열 자체가 전달되는것이아닌 배열 각 요소들이 전달되는것이다.
function color(a,b,c){
console.log(this);
console.log(a+b+c);
}
const bright = {name:'skyblue'};
color.call(bright,1,2,3); // {name: 'skyblue'} , 6
color.apply(bright,[1,2,3]); // {name: 'skyblue'} , 6
bind도 apply,call과 같은 역할이다.
bind 또한 this를 내가 원하는 특정 객체와 묶어준다.
다만 차이점은 apply,call은 객체를 묶어줌과 동시에 실행되고
bind는 묶어주기만하고 실행되지는 않는다.
function color(){
console.log(this);
}
const bright = {name:'skyblue'};
const c=color.bind(bright);
c(); // {name: 'skyblue'} , 6
-메서드 내에서 bind해보기
(blue메서드의 this를 red메서드에 묶어준다.)
const color={
name:'skyblue',
red:function(){
blue= function(){
console.log(this); //{name: 'skyblue', red: ƒ}
console.log(this.name); // 'skyblue'
}.bind(this);
blue();
},
}
color.red();
화살표함수는 스스로 this가 없다.
위에 다뤘던 일반 함수들은 자신이 속한 객체를 가리키지만
화살표함수에서 this는 항상 상위 스코프를 상속받는다.
call,apply같은걸로 this를 바인딩 할 수 없다. 따라서 화살표함수에서 this는 문맥을 항상 유지한다.
function A(){
this.name='a';
return{
name:"return",
result:()=>{
console.log(this.name);
}
}
}
const a = new A();
a.result(); // 'a'
result의 this는 상위스코프인 a를 가리키고
반면 일반 메서드는 자신이 속한 객체를 가리킨다.
function A(){
this.name='a';
return{
name:"return",
result(){
console.log(this.name);
}
}
}
const a = new A();
a.result(); //'return'
this는 함수를 어떻게 정의하고 호출하냐에 따라서 가리키는 값이 다르므로 항상 주의하면서 사용해야한다.