ES6 / 헷갈리는 그 이름 this 1편 / 함수호출
일단 HTML5 CSS3로 코드를 접한 나는 JS배우기 시작하고나서 하루하루가 쥰내빡치는 일들의 연속이었다.
그 중 지금도 헷갈리는 this를 지금 이 시간에 정리해보자.
Js에서함수는 호출될 때 매개변수로 전달되는 인자값 이외에 arguments 객체와 this를 암묵적으로 전달받는다.
Js의 경우 함수호출방식에 따라 this에 바인딩할 객체가 동적으로 결정됨.
함수가 어떻게 호출되었는가에 따라 this에 바인딩할 객체가 결정된다는 뜻임.
( 함수의 상위 스코프를 결정하는 방식인 렉시컬 스코프(Lexical Scope)는 함수를 선언할 때 결정됨.
this 바인딩과 헷갈리지 않도록 주의해야함. )
함수를 호출하는 방식은 아래와 같이 다양함.
- 함수호출
- 메소드 호출
- 생성자 함수 호출
- apply/call/bind 호출
var foo = function () {
console.dir(this);
};
// 1. 함수 호출
foo(); // window
// window.foo();
// 2. 메소드 호출
var obj = { foo: foo };
obj.foo(); // obj
// 3. 생성자 함수 호출
var instance = new foo(); // instance
// 4. apply/call/bind 호출
var bar = { name: 'bar' };
foo.call(bar); // bar
foo.apply(bar); // bar
foo.bind(bar)(); // bar
함수호출📢
전역객체는 모든 객체의 유일한 최상위 객체를 의미함.
Browser-side 에서는 window 객체를 ,
Server-side에서는 global 객체를 의미함.
전역객체는 전역스코프(Global Scope)를 갖는 전역변수(Global variable)를 프로퍼티로 가진다.
글로벌 영역에서 선언한 함수는 전역객체의 프로퍼티로 접근할 수 있는 전역변수의 메소드이다..
말이 쥰내 생소하고 어렵긴한데 그림으로 보면 그리 어렵지 않다.
var ga = 'Global variable';
console.log(ga); // Global variable
console.log(window.ga); // Global variable
function foo() {
console.log('invoked!');
}
window.foo(); // invoked
기본적으로 this 는 전역객체(Global object)에 바인딩 된다.
전역함수는 물론이고 심지어 내부함수의 경우도 this는 외부함수가 아닌 전역객체에 바인딩 된다.
function foo() {
console.log("foo's this: ", this); // window
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
foo();
또한 메서드의 내부 함수일 경우에도 this는 전역객체에 바인딩 된다.
메서드는 객체에 종속적인 함수를 일컫는다.
var value = 1;
var obj = {
value: 100,
foo: function() {
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // 100
function bar() {
console.log("bar's this: ", this); // window
console.log("bar's this.value: ", this.value); // 1
}
bar(); // bar의 this는 전역객체에 바인딩.
}
};
obj.foo();
콜백함수의 경우에도 this 는 전역객체에 바인딩 된다.
내부함수는 일반함수,메서드,콜백함수 어디에 선언되었든 관계없이 this는 전역객체를 바인딩 한다.
내부함수의 this가 전역객체를 참조하는 것을 회피하려면 that을 사용하면 된다.
var value = 1;
var obj = {
value: 100,
foo: function() {
var that = this; // Workaround : this === obj
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // 100
function bar() {
console.log("bar's this: ", this); // window
console.log("bar's this.value: ", this.value); // 1
console.log("bar's that: ", that); // obj
console.log("bar's that.value: ", that.value); // 100
}
bar();
}
};
obj.foo();
위 방법 이외에도 JS는 this를 명시적으로 바인딩 할 수 있는 apply, call, bind 메서드를 제공한다.
var value = 1;
var obj = {
value: 100,
foo: function() {
console.log("foo's this: ", this); // obj
console.log("foo's this.value: ", this.value); // 100
function bar(a, b) {
console.log("bar's this: ", this); // obj
console.log("bar's this.value: ", this.value); // 100
console.log("bar's arguments: ", arguments);
}
bar.apply(obj, [1, 2]);
bar.call(obj, 1, 2);
bar.bind(obj)(1, 2);
}
};
obj.foo();
다음 글은 메서드 호출!