자바스크립트에서 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는 바인딩과 동시에 함수를 실행.