this와 바인딩을 시작하기전에 이 포스팅의 시작은 Execution context이었다. 이번 포스팅 하는 이유는 Execution context를 좀더 보완하기 위해서 이다.
Execution Context 관련 TIL
위 벨로그를 어느정도 정리를 하였지만 this
를 모두 설명하기는 어려웠다. 더구나 앞으로 다룰 화살표 함수
나 전에 다루었던 scope
설명하기 어렵기는 마찬가지이다. 이번 this
와 바인딩을 통해서 조금 더 정리되길 바란다.
우선 this
는 자기자신이라는 추상적인 의미와 더불어 현재 가리키는 객체 this
를 결정한다는 의미로 바인딩
으로 표현한다고 한다.
"대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정된다."
호출방법에 의해서이기 결정되기 때문에 this를 바인딩하는 것은 동적
이라고 보면된다. 그리고 별다른 호출이 없다면 this
는 전역객체를 가르킨다. 전역 객체라 함은 브라우저로는 window
객체 이며 javascript에서는 global
객체를 의미한다.
함수를 어떤 객체의 메소드로 호출 하면 this
의 값은 그 객체를 사용한다고 한다.
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); // 37
이 경우 어떻게 호출했느냐에 따라 결과값이 바뀔수 있다.
var o = {
prop: 37,
f: function() {
return this.prop;
}
}
console.log(o.f()); // 37
const calling1 = o.f
console.log(calling1()) // undefined
이유인즉 this
의 바인딩은 동적
이기 때문이다. 아래 변수명 "calling1"의 this
는 전역객체를 가르킬것이다.
var o = {
prop: 37,
f: function() {
console.log(window === this) //해당콘솔을 추가하였다.
return this.prop;
}
}
console.log(o.f());
//false
// 37
const calling1 = o.f
console.log(calling1())
//true
// undefined
new 키워드와 함께 생성자로 사용 하면 this
는 새로생긴 객체에 묶인다고 한다.
a = 10
function C() {
this.a = 37;
}
var o = new C();
console.log(o.a); // 37
console.log(this.a); // 10
this 바인딩에서 헷갈리는 것이 있다면, 화살표 함수와 엄격 모드일 것이다. 우선 엄격 모드에 대해서 정리한 내용은 다음 링크에서 참고하자.
엄격모드(Strict mode)
this의 바인딩은 기본적으로 전역객체
를 따르는데 엄격모드
에서는 제한 된다고 한다. 제한되는 이유는 브라우저에서 보안성을 갖추기 위함이라고 한다.
//use strict mode
'use strict';
var v = "Hi! I'm a strict mode script!";
console.log(this.v) //undefined
//use sloppy mode?
var v = "Hi! I'm a strict mode script!";
console.log(this.v) //"Hi! I'm a strict mode script!"
기본적으로 javascript의 this
가 바인딩되는 것은 어떻게 호출했냐에 따라 동적
으로 결정되었다. 하지만 ES6 에서 추가된 화살표 함수로 this
를 사용할 경우, 정적
으로 바인딩 된다고 한다. 또한 call, apply, bind 메서드로도 this
를 변경할 수 없다고 한다.
this.x = 1
const aaa = function(){
return this.x
}
const bbb=()=>{
return this.x
}
console.log(aaa()) // 1
console.log(bbb()) // 1
console.log(aaa.call({x:10})) // 10
console.log(bbb.call({x:10})) // 1
화살표 함수 내부의 this
는 언제나 상위 스코프의 객체를 가리킨다고 한다. 이를 lexcical scope라고 한다. 이 때문에 콜백 함수로 사용하기는 편리하다고 하지만, 안되는 경우도 있어서 주의해야 한다고 한다.
맞는 예가 아닐 수도 있다. filter 메소드의 thisArg에 대한 예이다.
let a = [1, 2, 3, 4, 5];
x = 2 //전역객체
let result1 = a.filter(function(el){
return el > this.x
},
{x : 3}
);
console.log(result1) // [4,5]
//함수 안에 있는 this를 바인딩 한 것이다.
//화살표 함수는 정적 스코프를 따른다.
let result2 = a.filter((x)=> x > this.x, {x:3})
console.log(result2) // [3,4,5]
앞에서 계속 언급하였듯이 this
는 동적
으로 바인딩 한다. 하지만 bind()를 사용할 경우 this
bind의 매개변수로 지정 된다.
this.x = 9
var module = {
x: 81,
getX: function() { return this.x }
};
module.getX() // 81
var retrieveX = module.getX
retrieveX() // 9 - 전역 스코프에서 호출 되었기 때문!
var boundGetX = retrieveX.bind(module)
boundGetX() // 81
추가적으로 bind()와 call(), apply()에 관해서도 정리한 벨로그가 있으니 참고바란다.
call(), apply(), bind()?
꽤 오래전인거 같은데 filter메소드에 thisArg를 보면서 알아보다가 여기까지 온거 같다. 알게 된것도 많았지만, 여전히 더 알아봐야 할것들이 많다. 실행 컨텍스트나 scope는 복습이 필요하다. 개인 일정 때문일수도 있었지만 시간을 쪼개서 글을 쓴다는 것이 정말 쉬운 일이 아니었다. 두서없이 써버린게 되어서 중간 중간 난감하기도 하였다. 부족한것은 다듬어야겠다.
(220725) typescript를 배우면서 전체적으로 벨로그를 수정하였다. 곳곳에 부족한 것들이 많아서 부끄러웠다. 나중에 볼 때도 또 그럴려나..?
[this, MDN, 2022년06월17일 접속]
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
[Strict mode, MDN, 2022년06월17일 접속]
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Strict_mode
[{풀스택} JavaScript 8강 - Strict mode와 관련 지식들, 시니어코딩 YouTube, 2022년06월18일 접속]
https://youtu.be/5k_cpzg6UwI
[Function.prototype.bind(), MDN, 2022년06월20일 접속]
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
[[10분 테코톡] 🥦 브콜의 This, 우아한Tech YouTube, 2022년06월20일 접속]
https://youtu.be/7RiMu2DQrb4
[자바스크립트 this 바인딩이란?, danmin-velog, 2022년06월20일 접속]
https://velog.io/@danmin20/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-this-%EB%B0%94%EC%9D%B8%EB%94%A9%EC%9D%B4%EB%9E%80
[자바스크립트 this란 무엇인가? | 웹 개발 입문자들을 위한 this 강좌!,
짐코딩의 CODING GYM YouTube, 2022년07월25일 접속]
https://youtu.be/GteV4zfqPIk