1. 글에 대해
-
이 글은 ES5 및 ES6 Arrow Function 안에서 this 값이 어떤식으로 평가되는지에 대한 내용을 다루고있다.
-
또한 모든 결과는 Chrome 브라우저를 통해 테스트된 결과입니다.
2. ES5 & this
-
this 값 초기화 테스트
// A 함수 객체를 선언한다. function A() { function B() { // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다. console.log(this); // global Object } // AO 에 포함된 내부 함수를 호출한다. B(); // AO.B(); // 초기화된 this 값을 반환한다. return this; } // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다. console.log(A()); // global Object // this 는 생성된 인스턴스로 초기화된다. console.log(new A()); // A Object // this 는 null 로 초기화되며, null 은 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다. console.log(A.call(null)); // global Object // this 는 전달된 {x: 1} 객체로 초기화된다. console.log(A.call({x: 1})); // Object {x: 1} // this 는 전달된 {x: 2} 객체로 초기화된다. console.log(A.apply({x: 2})); // Object {x: 2} // this 는 전달된 {x: 2} 객체로 초기화된다. console.log(A.bind({x: 3})()); // Object {x: 3}
-
바인딩된 익명 함수 내부에서의 this 값
// 버튼 객체를 생성한다. var btnElem = document.querySelector('#btn1'); // 생성된 버튼 객체에 click 이벤트를 바인딩한다. btnElem.addEventListener('click', function(){ // 이 경우 this 값은 target element 인 btnElem 객체를 가리킨다. console.log(this); // btnElem object });
-
bind 함수를 통해 (바인딩된)함수 내부 this 값을 전역 스코프의 this 값으로 초기화 시킬 수 있다.
// 버튼 객체를 생성한다. var btnElem = document.querySelector('#btn1'); // 생성된 버튼 객체에 click 이벤트를 바인딩한다. btnElem.addEventListener('click', function(){ // 이 경우 this 값은 bind 함수를 통해 초기화된 this 값을 가리킨다. console.log(this); // global object }.bind(this));
-
this 값 초기화 테스트 in Strict Mode
- Strict Mode 에서는 this 값이 null, 또는 undefined 인 경우, 암묵적으로 global Object 로 변환되지 않는다.
// A 함수 객체를 선언한다. function A() { // Strict Mode 선언 'use strict'; function B() { // this 는 undefined 로 초기화된다. console.log(this); // undefined } // AO 에 포함된 내부 함수를 호출한다. B(); // AO.B(); // 초기화된 this 값을 반환한다. return this; } // this 는 undefined 로 초기화된다. console.log(A()); // undefined // this 는 global object 로 초기화된다. console.log(this.A()); // this 는 생성된 인스턴스로 초기화된다. console.log(new A()); // A Object // this 는 null 로 초기화된다. console.log(A.call(null)); // global Object // this 는 전달된 {x: 1} 객체로 초기화된다. console.log(A.call({x: 1})); // Object {x: 1} // this 는 전달된 {x: 2} 객체로 초기화된다. console.log(A.apply({x: 2})); // Object {x: 2} // this 는 전달된 {x: 2} 객체로 초기화된다. console.log(A.bind({x: 3})()); // Object {x: 3}
-
this 값 초기화 테스트 in Object
- 객체 메서드에서의 this 는 해당 메서드를 내부 프로퍼티로 소유한 객체를 가리킨다.
var A = { x: function(){ var B = function(){ // this 는 undefined 로 초기화되며, undefined 는 this 로 평가될 수 없으므로, 암묵적으로 global Object 로 변환된다. console.log(this); // global Object } // AO 에 포함된 내부 함수를 호출한다. B(); // AO.B(); // 초기화된 this 값을 반환한다. return this; } }; // 이 경우 this 는 해당 함수를 내부 프로퍼티로 소유한 객체를 가리킨다. console.log(A.x()); // A Object
3. ES6 Arrow Function & this
-
Arrow Function 은 자신만의 this, arguments, super, new.target 이 할당되지 않는다.
-
Arrow Function 의 this 값은 함수가 위치한 지점을 둘러싼, 전역/함수 스코프의 this 값을 가리키며, 바인딩된 후 변하지 않는다.
// global execution context
// Arrow Function 을 할당한다.
var A = () => {
// A function execution context
var B = () => {
// B function execution context
// 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(global Object) 값으로 초기화된다.
console.log(this);
}
B();
// 초기화된 this 값을 반환한다.
return this;
};
// this 는 global object 로 초기화된 후 변하지 않는다.
console.log(A()); // global Object
// this 는 global object 로 초기화된 후 변하지 않는다.
console.log(this.A()); // global Object
// new 연산자를 통해 새로운 인스턴스 생성 시 에러가 발생한다.
try {
console.log(new A());
}
catch(e){
// Uncaught TypeError: () => this is not a constructor
console.log(e.message);
}
// this 는 global object 로 초기화된 후 변하지 않는다.
console.log(A.call(null)); // global Object
// this 는 global object 로 초기화된 후 변하지 않는다.
console.log(A.call({x: 1})); // global Object
// this 는 global object 로 초기화된 후 변하지 않는다.
console.log(A.apply({x: 2})); // global Object
// this 는 global object 로 초기화된 후 변하지 않는다.
console.log(A.bind({x: 3})()); // global Object
- 바인딩된 익명 (Arrow)함수 내부에서의 this 값
// 버튼 객체를 생성한다.
var btnElem = document.querySelector('#btn1');
// 생성된 버튼 객체에 click 이벤트를 바인딩한다.
btnElem.addEventListener('click', () => {
// 이 경우 arrow function 의 this 값은 해당 함수를 둘러싼 전역 스코프의 this 값으로 초기화된다.
console.log(this); // global Object
// 버튼 객체를 통해 명시적으로 접근한다.
console.log(btnElem);
});
- 함수 객체 내부에서의 Arrow Function 의 this 값
function A(){
// arrow function
var B = () => {
// 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(global Object) 값으로 초기화된다.
console.log(this); // global Object
};
B();
// 초기화된 this 값을 반환한다.
return this;
}
// this 는 global Object 로 초기화된다.
A();
- 생성자 함수 객체 내부에서의 Arrow Function 의 this 값(Arrow Function 의 this 값을 동적 바인딩하기위한 방법)
function A(){
// arrow function
var B = () => {
// 이 경우 this 는 (B)함수를 둘러싼, (A)함수 스코프의 this(A Object) 값으로 초기화된다.
console.log(this); // A Object
};
B();
// 초기화된 this 값을 반환한다.
return this;
}
// this 는 생성된 인스턴스로 초기화된다.
console.log(new A()); // A Object
- 객체 메서드에서의 this 는 해당 메서드를 둘러싼, 전역 스코프의 this 값으로 초기화된다.
var A = {
normalMethod: function(){
return this; // A object
},
arrowMethod: () => {
return this; // global object
}
};
// 이 경우 this 는 해당 함수를 내부 프로퍼티로 소유한 객체를 가리킨다.
console.log(A.normalMethod()); // A Object
// 이 경우 this 는 (arrowMethod)함수를 둘러싼, 전역 스코프의 this(global Object) 값으로 초기화된다.
console.log(A.arrowMethod()); // global Object
- Arrow Function 내부에서의 this 값 변경
var A = {
arrowMethod: () => {
var bindFn = function(){
console.log(this); // A object
}.bind(A)();
return this;
}
};
console.log(A.arrowMethod()); // global Object
- 그 밖의 테스트
// 객체를 반환하기 위해서는 괄호 연산자 또는 return 문을 사용해야한다.
{
let a = () => {x: 1 };
console.log(a()); // undefined
}
{
let a = () => ({x: 1});
console.log(a()); // {x: 1} object
}
{
let a = () => { return {x: 1}; };
console.log(a()); // {x: 1} object
}
// IIFE(즉시 실행 함수) 는 아래와 같이 표현될수 있다.
console.log((() => 1)()); // 1