this

nabisorry·2019년 10월 31일
1

JavaScript

목록 보기
1/9
post-custom-banner

1. this

this 는 호출자를 가르킨다.

this를 활용?하는 5가지의 경우

1.전역공간에서 (window/global 전역객체)
2.함수내부에서 (window/global 기본적으로는 전역객체이며 바인딩으로 변경할수 있다.)
3.메소드 호출시 (메소드 호출한 주체(메소드명 .앞까지))
4.callback에서 (기본적으로는 함수내부와 동일 단 call,apply,bind 호출로 변경할수 있음)
5.생성자함수에서 (인스턴스)

1.1 전역공간에서 this

전역공간 에서의 this는 전역객체이다.

ddddd.png

1.2 함수내부에서 this

함수 내부에서 this는 기본적으로 전역객체이다.


function a() {
   console.log(this);
   function b() {
      console.log(this);
   }
   b();
}
a(); //window window

기본적인 함수에서 this는 전역객체이며 외부 내부 함수에서도 전역객체이다.
call,apply,bind는 아래에서 정리

1.3 메서드에서 this

메서드에서 this는 메서드를 호출한 주체이다.

let a = {
   b: function() {
      console.log(this);
   }
};
a.b(); // 객체 a
//////////////////////////////////
let a = {
   b: {
      c: function() {
         console.log(this);
      }
   }
};
a.b.c(); // 객체 b반환

a.b() 에서 this 는 객체 a를
a.b.c() 에서 this는 객체 b를 가리킨다.

1.4 callback에서 this

기본적으로는 함수내부에서와 동일하지만 call,apply,bind 메서드를 통해 this를 변경할수있다.

1.4.1 call,apply,bind

call,apply,bind는 함수를 호출하는 메서드이다. MDN에서 call,apply,bind 구문이다.

fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])
func.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg는 설정해줄 this는 전달해주는 매개변수이다.
call과 bind는 두 번째 매개변수로 함수에 전달해줄 인자들을 일일이 적어준다.
apply는 배열로 묶어서 한 번에 전달해준다.
call과 apply는 즉시 호출하는 메서드이며 bind는 새로운 함수를 생성할 뿐 즉시 호출은 아니다

function a(x,y,z) {
   console.log(this,x,y,z)
}
let b = {
   c: 'obj'
}

a.call(b,1,2,3)//{c: "obj"} 1 2 3
a.apply(b,[1,2,3])//{c: "obj"} 1 2 3

let c = a.bind(b,1,2,3)
c()//{c: "obj"} 1 2 3

위에 코드에서 a(1,2,3) 호출하면 window 1 2 3 이 출력될 것이다.
하지만 call과 apply 메서드로 각각 this 값에 b를 담았고 그 결과 출력은 {c: "obj"} 1 2 3로 둘 다 똑같이 출력된다.
bind는 즉시 호출이 아니기 때문에 변수에 담아서 호출하면 {c: "obj"} 1 2 3 같은 값을 출력한다.

다시 callback this로 돌아와서

function callback() {
   console.log(this);
}
let obj = {
   a: function(cb) {
      cb(); //현재 this는 window
   }
};
obj.a(callback);

위 코드에서 callback 함수의 this는 window이다.
cb()코드를 cb.call(this)로 바꿔주면 this는 obj가 된다. 그 이유는 콜백 함수의 제어권을 갖고 있는 메서드 a()의 this는 obj이고 call 이란 메서드를 통해 다시 this를 넘겨줌으로 window가아닌 obj가 된다.

function callback() {
   console.log(this);
}
let obj = {
   a: 1
};

setTimeout(callback.bind(obj), 100);

setTimeout 은 this에 대한 별도의 처리가 없기 때문에 window이다. 앞에 코드와 달리
setTimeout의 콜백 처리를 변경할 수 없기 때문에
(cb() -> cb.call(this)로 호출을 변경 한 것처럼)
callback.bind(obj)로 처리한다.
bind를 사용한 이유는 call과 apply는 즉시 호출이기 때문에 조건에 따라 실행되는 이벤트 함수에서는 bind를 통해 함수로 넘겨준다.

이벤트 리스너는 또 달라진다.

//버튼 하나 만들고 
document.querySelector("body").prepend(document.createElement("button"));

document.querySelector("button").addEventListener("click", function() {
   console.log(this); //<button></button>
});

해당 코드의 this는 으로 이벤트 리스너 함수는 내부적으로 this를 DOM 객체를 가리키도록 설정한다.
여기서 조금더 신경 쓰자면

//버튼생략 
document.querySelector("button").addEventListener("click", function() {
   console.log(this);
   function inner() {
      console.log(this);
   }
   inner(); //window 
});

콜백 함수 내에서 선언된 inner 함수는 또 기본 원칙에 따라 this는 window 이다.
이 문제를 해결하기 위해서는
스코프 체인을 이용해서 해결해주거나 화살표 함수를 이용해 해결해준다.

스코프체인

//버튼생략 
document.querySelector("button").addEventListener("click", function() {
   console.log(this);
   let self = this;
   function inner() {
      console.log(self);
   }
   inner();
});

화살표함수

//버튼생략
document.querySelector("button").addEventListener("click", function() {
   console.log(this);
   let inner = () => {
      console.log(this);
   };
   inner();
});

화살표 함수에서 this는 상위 함수에 this를 따른다.
this의 변화를 굵직하게 정리했지만 이벤트 리스너 함수에서처럼 내부적으로 this를 다르게 정의하는 경우가 있다고
한다. 라이브러리를 사용할 때 this를 항상 체크해야 한다 (아직은 뭐... 와닿지 않는다..)

1.5 생성자함수에서 this

이부분은 전에 생성자 함수 정리하면서 겪어봤던 부분이다.

function Person(a,b) {
    this.name = a
    this.age = b
}

let a = new Person('dabin',28)

여기서 this는 인스턴스(코드에서는 a)를 가리킨다.


참고
javascript핵심강의
제로초블로그
MDN

profile
쿨럭쿨럭
post-custom-banner

0개의 댓글