this 라는 키워드는 다른 언어에서도 많이 사용된다.
하지만 자바스크립트에서는 다른 언어들과는 다르게 동작을 한다.
대부분의 경우 this의 값은 함수를 호출한 방법에 의해 결정이 된다.
실행중에는 할당으로 설정할 수 없고 함수를 호출할 때 마다 다를 수 있다.
ES5는 함수를 어떻게 호출했는지 상관하지 않고 this 값을 설정할 수 있는 bind 메서드가 추가 되고,
ES6는 스스로의 this 바인딩을 제공하지 않는 화살표 함수가 추가 되었다.
화살표 함수에서의 this는 렉시컬 컨텍스트안의 this 값을 유지한다.
const obj = {
num : 10,
foo : function() {
return this.num
}
}
console.log(obj.foo()) // 10
실행 컨텍스트의 프로퍼티는 비엄격 모드에서 항상 객체를 참조하며, 엄격 모드에서는 어떠한 값이든 될 수 있다.
this는 기본적으로 전역 객체를 참조한다.
브라우저에서는 전역 객체인 window
를 참조하고 있다.
console.log(this === window) // ture
a = 10
console.log(window.a) // 10
this.b = "string"
console.log(window.b) // "string"
console.log(b) // "string"
함수 내부에서 this의 값은 호출한 방법에 의해 좌우된다.
function window () {
return this
}
// 브라우저
window() === window // true
// Node.js
window() === global // true
strict mode가 아니며 this의 값이 호출에 이해 설정되지 않으므로, 기본값으로 브라우저에서는 window인 전역 객체를 참조한다.
반면에 strict mode에서 this 값은 실행 문맥에 진입하여 설정되는 값을 유지하므로 다음 예시에서 보여지는 것 처럼 this는 undefined로 남아 있다.
function strict () {
"use strict"
return this
}
strict() === undefined // true
ES5에서는 bind가 추가됐다.
bindFunction.bind()
를 호출하면 f와 같은 코드와 범위를 가졌지만 this 원본 함수를 가진 새로운 함수를 생성한다.
새 함수의 this는 호출 방식과 상관 없이 영구적으로 bind()
의 첫 번째 매개변수로 고정된다.
function bindFunction () {
return this.a
}
const a = bindFunction({a : 'aBind'})
console.log(a()) // 'aBind'
const b = a.bind({a: 'bBind'}) // bind는 한번만 동작
console.log(b()) // 'aBinde'
화살표 함수에서 this는 자신을 감싹 정적 범위이다.
전역 코드에서는 전역 객체를 가리킨다.
const obj = this
const foo = () => this
console.log(foo() === obj) true
화살표 함수는 call(), bind(), apply() 를 사용해 호출할 때 this의 값을 정해주더라도 무시한다.
사용할 매개변수를 정해주는 건 문제가 없지만, 첫번째 매개변수는 null을 지정해야 한다.
const obj = {objfunc : foo}
console.log(obj.objfunc() === globalObject) // true
console.log(foo.call(objfunc) === globalObject) // true
foo = foo.bind(objfunc)
console.log(foo() === globalObject) // true
어떠한 방법을 사용하더라도 foo
와 this
는 생성 시점의 것으로 설정된다.
다른 함수 내에서 생성된 화살표 함수에도 동일하게 적용된다.
this는 싸여진 렉시컬 컨텍스트의 것으로 유지된다.
함수를 어떤 객체의 메서드로 호출하면 this의 값은 그 객체를 사용한다.
다음 예제에서 o.f()를 실행할 때 O 객체가 함수 내부의 this와 연결이 된다.
const o = {
num: 10,
f: function() {
return this.num;
}
};
console.log(o.f()); // 10
객체의 메서드로 사용하면 함수가 정의된 방법이나 위치에 전혀 영향을 받지 않는 것에 유의해야한다.
그리고 위와 같이 만들때 선언하지 않고 따로 선언한 함수를 추가하는 것도 가능하다.
const o = { num : 10 }
function foo () {
return this.num
}
o.f = foo
console.log(o.f()) // 10
이는 함수가 객체의 요소 f로 부터 호출 되는 것만 중요하다는 것을 보여준다.
출처 : mdn