https://medium.com/sjk5766/javascript-this-binding-%EC%A0%95%EB%A6%AC-ae84e2499962
JavaScript 에서 함수의 this 키워드는 다른언어와 조금 다르게 작동한다고 한다.
this와 실행 컨텍스트
자바스크립트는 스크립트 언어로, 인터프리터에 의해 줄 단위로 읽혀서 해석 실행됨
인터프리터에 의해 현재 실행되는 JS의 환경을 실행 컨텍스트라고 함!
자바스크립트 내부에서 이러한 실행 컨텍스트를 스택으로 관리하고, 실행되는 시점에 자주 변경되는 실행컨텍스트를 this가 가리킨다!
: 기본적으로 this는 전역 객체를 가리키게 되는데 Node 환경에서는 global 객체,Browser에서는 Window 객체를 가리킴!
: 일반적인 함수 내부에서 this를 호출하면 전역 객체!
, strict 모드를 사용하는 경우에는 그렇지 않음 (undefined 반환됨)
즉시 실행함수의 경우에도 마찬가지!
function checkThisInNormalFunc() {
console.log(this === window) // true
}
checkThisInNormalFunc()
console.log(this === window) // true
// strict 모드
function checkThisInNormalFunc() {
'use strict';
console.log(this === window) // false
}
checkThisInNormalFunc()
console.log(this === window) // true
객체 내부의 메소드에서 this를 binding 할 경우, 그 객체 자신을 가리키게 됨
this가 참조되는 위치가 중요한게 아니라 어디서 어떻게가 this를 포함하는 코드를 호출하냐가 중요!
var obj1 = {
name: "seo",
print: function() {
console.log(this.name); // this가 참조되는 위치
}
}
var obj2 = { name: "jeong", print: obj1.print };
var name = "kuk";
var print = obj1.print;
print(); // kuk 일반적인 함수호출 (this는 전역객체)
obj1.print(); // jeong (객체 메소드 방식으로 호출)
obj2.print(); // seo (객체 메소드 방식으로 호출)
함수 내부에서 this는 전역 객체를 가리킴!
function printName() {
var lastName = "seo";
this.firstName = "jeong kuk"
console.log(this.lastName + " " + this.firstName)
}
var lastName = "kim";
printName(); // kim jeong kuk
var o = new printName(); // undefined jeong kuk
printName 함수 안에 lastName과 this로 접근함 firstName이 있음
firstName은 전역객체! (함수내부 this = 전역객체)
대신 new를 선언할 경우 this 는 전역객체가 아닌 생성된 객체 자체를 가리키게됨
따라서 this로 접근한 firstName은 정상적인 값을 가져오지만 더 이상 전역객체가 아니어서 lastName은 undefined로 나옴
call, apply 메소드는 첫 번째 인자로 실행 컨텍스트를 인자로 전달함
printName.call(obj)
에서 obj 를 전달할 때, this 가 obj의 실행 컨텍스트를 가리키게 됨
function printName() {
console.log(this.name)
}
var name = "seo"
printName(); // seo
var obj = {name: "jeong kuk"}
printName.call(obj); // jeong kuk
es6 에서 추가된 화살표 함수 내부에서 this를 사용할 경우 , this에 바인딩할 객체가 정적으로 결정되기 때문에 call, apply, bind 로 this를 변경할 수 없음!
window.x = 1;
const normal = function () { return this.x; };
const arrow = () => this.x;
console.log(normal.call({ x: 10 })); // 10
console.log(arrow.call({ x: 10 })); // 1
화살표 함수 내부의 this는 언제나 상위 스코프의 객체를 가리킴(lexical this: 문맥적 this), 때문에 콜백 함수로 사용하기 편리하지만 화살표 함수를 사용해서는 안되는 경우도 존재해서 주의!!!
객체의 메서드를 화살표 함수로 선언할 경우, this는 해당 객체가 아닌 전역 객체를 가리키게되므로 주의해야함
이 경우에는 es6의 축약 메소드 표현을 사용하는 것이 좋다.
var obj = {
foo: "foo",
print1: () => { console.log(this.foo) },
print2 () { console.log(this.foo) }
}
obj.print1() // undefined
obj.print2() // foo
var Foo = () => {}
console.log(Foo.prototype) // undefined
var foo = new Foo() // TypeError: Foo is not a constructor