You don't know JS - this
this란 무엇인가?
어떤 함수를 호출하면 context가 만들어지는데,
여기에는 함수가 실행될 때 필요한 정보들이 담겨져있다.
this는 이 context 중 하나로, 실행되는 동안 이용가능하다.
오해 2가지
- this가 함수 그 자체를 가리킨다는 오해
- this가 함수의 스코프를 가리킨다는 오해
this는 함수 호출 당시 상황에 따라 context가 정해진다.
결국, 어떻게 호출했느냐에 따라 this 바인딩이 정해짐
호출부와 호출 스택
function baz() {
// 호출 스택 baz
// 호출부 전역 스코프 내부
bar()
}
function bar() {
// 호출 스택 baz -> bar
// 호출부 baz
foo()
}
function foo() {
// 호출 스택 baz -> bar -> foo
// 호출부 bar
console.log("hi")
}
this 바인딩은 호출부와 연관되어 있기에, 이를 유심히 봐야함
바인딩 4가지 방법
- 기본 바인딩
function foo() {
console.log(this.a)
}
var a = 2
foo(); //2
foo 실행 시 함수 내부의 this는 전역 객체를 가리키게 된다.
- 암시적 바인딩
function foo() {
console.log(this.a)
}
var obj = {
a: 2
foo: foo
}
obj.foo() // 2
obj
안에서 foo 함수를 프로퍼티로 참조하고 있고,
호출 시점에 obj 객체는 준비되어 있는 상태이므로, context가 this에 바인딩 된다.
따라서 this.a 는 obj.a가 됨
만약 객체 프로퍼티 참조가 체이닝이라면 가장 인접한 컨텍스트가 바인딩 됨
어떻게 호출하냐가 중요한 이유가 여기서 나온다.
다음 코드를 봐보자function foo() { console.log(this.a) } var obj = { a: 2, foo: foo } var a = 1 var bar = obj.foo bar(); // 1
bar는 obj의 foo를 참조하는 변수가 아닌, 그냥 foo를 직접 가르키는 레퍼런스임
- 명시적 바인딩
call()
,apply()
메서드로 직접 this에 바인딩 하는 방법이 있음
function foo() {
console.log(this.a)
}
var obj = {
a: 2
}
foo.call(obj) //2
위 예제처럼 호출시 call()
안에 바인딩할 객체를 넣어준다
- new 바인딩
함수 앞에new
연산자가 붙으면 일어나는 일
- 새 객체가 만들어진다.
- 그 객체에 Prototype과 함수의 Prototype이 연결된다.
- 생성된 객체는 함수의 this에 바인딩된다. 그 상태로 함수 실행
- 함수 실행 후 그 객체를 반환한다.
function foo(a) {
this.a = a
}
// 새 객체 만들고, 그 객체와 foo.prototype 연결한 뒤, foo 실행 후 객체 반환
var bar = new foo(2)
console.log(bar.a) // 2
바인딩 순서
명시적 바인딩 >> new 바인딩 >> 암시적 바인딩 >> 기본 바인딩
안전한 바인딩
만약 this 바인딩이 다른 것에 잘못 되는 일을 막고 싶다면
Obejct.create(null) 과 같은 빈 객체를 만들어 바인딩 시켜버리는 것도 방법
이러면 뜻하지 않은 부수효과가 전역 객체에서 발생하지 않는다.
--- 최종 정리 ---
var bar = new foo() // this는 새로 생성된 객체이다
var bar = foo.call(obj2) // this는 obj2이다
var bar - obj1.foo(); // this는 obj1이다
var bar = foo() // this는 전역객체다 (엄격모드에서는 undefined)
화살표 함수
화살표 함수는 위의 규칙을 따르지 않고, 스코프를 통해 알아서 this 바인딩 한다.
function foo() {
return (a) => {
console.log(this.a) // 여기서 this는 foo()에서 가져온다
}
}
var obj1 = {
a: 2
}
var obj2 = {
a: 3
}
var bar = foo.call(obj1)
bar.call(obj2) // 2
위를 보면 bar.call(obj2)
를 함에도 불구하고
foo에서 화살표 함수의 this는 obj1를 인 것을 볼 수 있다.
즉, 함수 호출에서 넣은 obj1을 그대로 사용하는 것
Author And Source
이 문제에 관하여(You don't know JS - this), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@leedc0101/You-dont-know-JS-this저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)