자바스크립트에서 this는 실행 컨텍스트가 생성될 때 함께 결정. 함수를 호출할 때 결정됨.
전역 공간에서 this
는 런타임 환경에 따라 다른데, 브라우져에서는 window
는 nodeJS에서는 global
객체를 말함.
var a = 1;
console.log(a);//1
console.log(window.a);//1
console.log(this.a);//1
전역 공간에 a
변수를 할당했을 뿐인데, window
,this
객체에 1이 나오는 이유는 자바스크립트의 모든 변수는 특정 객체(window)의 프로퍼티로써 동작 하기 떄문. 즉, 전역 변수를 선언하면 자바스크립트 엔진은 이를 전역객체의 프로퍼티로 할당.
var func = function(x){
console.log(this,x);
}
func(1);
var obj={
method:func
};
obj.method(2);
1 .func 변수에 익명함수를 할당후 func 함수 실행시 결과는
window
객체와1
이 나옴.
2 .obj 변수에 method프로퍼티에 func 함수를 할당 후 method호출시obj
객체와2
가 나옴.
즉, 함수를 어떻게 호출하느냐에 따라 this값이 달라짐.
var obj = {
A:function(){
console.log(this);
},
inner:{
B:function(){
console.log(this);
}
}
};
obj.A() // {inner:{...}, A:f}
obj.inner.B() // {B:f}
이전에 this에 대한 정의를 함수를 호출할 때 결정된다고했는데 이를 대입해보면 A
메서드를 호출하면 호출의 주체는 obj
객체이기 때문에 this
는 obj
객체가 나오고 B
메서드를 호출하면 호출의 주체는 obj객체의 inner
객체에서 호출했기 때문에 inner
객체가 나옴.
함수가 호출이 되는(=실행컨텍스트가 생성이 되는 순간) 순간에 this가 지정된다고했음. 그래서 함수에서의 this는 전역객체를 가리킴.
var obj1 = {
outer:function(){
console.log(this);
var innerFunc = function(){
console.log(this);
};
innerFunc();
var obj2 = {
innerMethod: innerFunc
};
obj2.innerMethod();
}
};
obj1.outer();
1 .
obj1
변수에 outer 프로퍼티를 할당하고 데이터는 익명함수를 할당하고 호출.
2 .obj1.outer
의 실행 컨텍스트가 생성. 호이스팅으로 인해innerFunc
,obj2
변수가 맨위로 올라옴.
3 . 콘솔에this
를 출력.this
에 대한 정의를 대입하면obj1
객체에서 호출했기때문에obj1
객체정보가 나옴.
4 .innerFunc
식별자에 익명함수 할당하고 호출.
5 .innerFunc
함수의 실행 컨텍스트가 생성. 이 때, 해당 함수를 단독으로 호출했기 때문에 콘솔에서this
는 전역객체가 나옴.(해당 함수 호출시.
이 없었기때문에 전역 객체가 나옴)
6 .obj2
변수에innerMethod
프로퍼티에는 변수 innerFunc의 익명함수 할당하고 innerMethod함수 메서드 호출.
7 . 콘솔에this
를 출력.this
에 대한 정의를 대입하면obj2
객체에서 호출했기때문에obj2
객체정보가 나옴.
즉, this 바인딩은 주변 환경이 중요한것이 아닌 누가 함수를 호출했느냐로 결정이 됨.
this
객체 값을 할당받은 변수를 선언하는 방법var obj = {
outer : function(){
console.log(this);
var innerFunc1 = function(){
console.log(this);
}
innerFunc1();
var self = this;
var innerFunc2 = function(){
console.log(self);
}
innerFunc2();
}
}
obj.outer();
var obj = {
outer : function(){
console.log(this);
var innerFunc1 = function(){
console.log(this);
}
innerFunc1();
var innerFunc2 = ()=>{
console.log(this);
}
innerFunc2();
}
}
obj.outer();
화살표 함수는 실행 컨텍스트 생성시 this 바인딩 과정 자체가 빠지게 되어, 상위 스코프의 this를 그대로 활용.
콜백함수를 매개변수로 받은 코드 내부에서 어떻게 처리 하느냐에 따라 this
가 달라짐.
function callback(){
console.log(this);
}
var obj1 = {
A:function(cb){
cb();
cb.call(this);
}
}
obj1.A(callback);
1 .
cb()
함수를 그냥 호출시 함수를 단독으로 호출했기 때문에window
객체가 나옴.
2 . call 함수를 통해cb()
this객체를 명시적으로 obj1객체로 바인딩 후 함수를 호출. 즉 obj1 객체가 나옴.
function callback(){
console.log(this);
}
var obj1 = { NAME : 'HGD' }
setTimeout(callback,500);
setTimeout(callback.bind(obj1),500);
- setTimeout 함수 500ms이후에 콜백 함수를 호출시 나오는
this
객체를 임의로 변경할수 없기때문에, 첫번째는window
객체가 나옴.- 이번에는 callback함수에
this
값을obj1
으로 바인딩 후, 500ms있다가 콜백함수를 호출하면,ob1
객체가 나옴.
//document.body.innerHTML = `<a id="click">클릭</a>`
document.querySelector('#click').addEventListener('click',function(){ console.dir(this)});
id가 click인 태그에 클릭이벤트 추가. 클릭 시 두번쨰 인자에 있는 콜백함수를 실행. 함수 내용은
this
객체를 출력하는데, 여기서는 id가 click인 태그에 관한 정보가 출력.
addEventListener 안의 소스 내용은 잘 모르지만, 콜백함수 실행시, 단독으로 호출이 아닌 명시적으로 태그정보를 바인딩하여 호출했음을 짐작할 수 있음.
new
명령어를 통한 인스턴스를 생성시, this
는 해당 인스턴스 객체가 됨.
function Human (name,age){
this.name=name;
this.age = age
}
var HongGilDong = new Human('홍길동',30);
console.log(HongGilDong); // {name:'홍길동',age:30}
Function.prototype.call(thisArg,[arg1,,,[arg2,,]])
함수를 즉시실행하는 메서드. 매개변수thisArg
에서 this를 바인딩하고 호출할 함수의 매개변수를 넣어서 실행.
Function.prototype.apply(thisArg,[argArray])
call
메서드와 완전 동일. 차이점은 호출할 함수의 매개변수를 배열로 받는것이 차이.
Function.prototype.bind(thisArg,[arg1,[arg2[,...]]])
call
메서드와 비슷하지만, 즉시 호출하지않고 넘겨 받은 this 및 매개변수인자들을 바탕으로 새로운 함수를 반환하는 메서드.
var obj ={
outer : function(){
console.log(this);
var innerFunc = function(){
console.log(this);
}
innerFunc.call(this);
}
}
obj.outer();
var obj ={
outer : function(){
console.log(this);
var innerFunc = function(){
console.log(this);
}.bind(this);
innerFunc();
}
}
obj.outer();
이전에 정리해뒀던 메서드의 내부 함수에서의 this 우회 방법.에서 우회 방법을 사용하지않고도 call
,bind
,apply
메서드를 통해 깔끔하게 처리가능.
ES6에서 새로 도입. 실행 컨텍스트 생성시 this
를 바인딩하는 과정이 제외됨. 즉, 함수 내부에 this
는 아예없기때문에 스코프체인상 가까운 this
에 접근.
var obj ={
outer : function(){
console.log(this);
var innerFunc = ()=>{
console.log(this);
}
innerFunc();
}
}
obj.outer();
이 때 innerFunc
함수에서의 this는 스코프체인상 가까운 obj
객체가 나옴.
this
, NodeJS는 global
객체)this
는 메서드 호출 주체가 됨.this
는 전역객체를 가리킴.this
는 해당 함수에서 정의된 바에 따르며, 특별한 경우는 전역객체를 가리킴.new
명령어를 통해 생성한 인스턴스 객체에서의 this
는 인스턴스 객체를 가리킴.call
,apply
,bind
메서드를 통해 this를 바인딩할수있으며, call
,apply
는 바인딩과 동시에 함수를 실행.