this - 클래스로 생성한 인스턴스(클래스로 만들 객체).
this는 실행 컨텍스트가 생성될 때 결정된다.(= bind된다) (함수가 호출될 때 결정)
전역 공간에서의 this
this = 전역 객체
런타임 환경에 따른 this
node - global 객체
browser - window 객체
메소드로 호출될 때 그 내부에서의 this
함수 vs 메소드
//함수는 독립적으로 기능
함수 - 함수명();
//메소드는 호출한 대상 객체에 대한 동작 수행
메소드 - 객체.메소드명();
this의 할당
// CASE1 : 함수
// 호출 주체를 명시할 수 없기 때문에 this는 전역 객체
var func = function (x) {
console.log(this, x);
};
func(1); // Window { ... } 1
// CASE2 : 메서드
// 호출 주체를 명시할 수 있기 때문에 this는 해당 객체(obj)
// obj는 곧 { method: f }
var obj = {
method: func,
};
obj.method(2); // { method: ƒ } 2
. []
(메소드는 객체.메소드 / 객체[메소드명])메소드 내부에서의 this
함수로서 호출할 때 함수 내부의 this
호출 주체를 알 수 없다.
this가 지정되지 않으면 this는 전역 객체
함수를 독립적으로 호출하면 this는 전역 객체다.
메소드의 내부함수에서 this
메소드 내부라고 해도 함수로서 호출하면 this는 전역 객체
var obj1 = {
outer: function() {
console.log('Test => ', this); // (1)
var innerFunc = function() {
console.log('Test => ', this); // (2), (3)
}
innerFunc();
var obj2 = {
innerMethod: innerFunc
};
obj2.innerMethod();
}
};
obj1.outer();
//Test => [object Object] (1) this === obj1 / 메소드로서 호출
//Test => [object global] (2) this === global / 함수로서 호출
//Test => [object Object] (3) this === obj2 / 메소드로서 호출
메소드의 내부 함수에서의 this 우회
변수를 활용하는 방법
var obj1 = {
outer: function() {
console.log(this); // (1) { outer: ƒ }
// AS-IS // 이전 방법
var innerFunc1 = function() {
console.log(this); // (2) 전역객체
}
innerFunc1();
// TO-BE // 이후 방법
var self = this; // this를 변수에 할당해서 활용
var innerFunc2 = function() {
console.log(self); // (3) { outer: ƒ }
};
innerFunc2();
}
};
// 메서드 호출 부분
obj1.outer();
화살표 함수(=this를 바인딩하지 않는 함수)
일반 함수롸 화살표 함수의 가장 큰 차이는 this binding 여부
var obj = {
outer: function() {
console.log(this); // (1) obj
var innerFunc = () => { // this binding 과정이 없었기 때문
console.log(this); // (2) obj // 이전 this를 유지
};
innerFunc();
}
}
obj.outer();
콜백 함수를 호출 시 그 함수 내부에서의 this
어떠한 함수, 메서드의 인자(매개 변수)로 넘겨주는 함수.
콜백 함수의 this도 전역 객체 참조 but this 지정 시 예외적으로 지정한 this를 참조
생성자 함수 내부에서의 this
생성자 - 구체적인 인스턴스를 만들기 위한 틀
function User(name) {
// this = {}; (빈 객체가 암시적으로 만들어짐)
// 새로운 프로퍼티를 this에 추가함
this.name = name;
this.isAdmin = false;
// return this; (this가 암시적으로 반환됨)
}
let user = new User("보라");
//위 아래 동일
/*
let user = {
name: "보라",
isAdmin: false
};*/
명시적 this binding 및 유사 배열 객체
call 메소드
호출 주체인 함수 즉시 실행
첫번째 매개 변수에 this로 binding할 객체를 넣어주면 명시적 this binding
// call
var func = function (a, b, c) {
console.log(this, a, b, c);
}
//no binding
func(1,2,3); // 전역 객체 1 2 3
// 명시적 binding
func.call({x: 1}, 4, 5, 6); // {x : 1} 4 5 6
apply 메소드
call과 동일 하나 나머지 부분만 배열 형태로
var obj = {
a : 1,
method : function (x, y) {
console.log(this.a, x, y);
}
};
// method 함수 안의 this는 항상 obj
// apply this binding
obj.method.apply({a: 2}, [5, 6]); // 2 5 6
call / apply 활용
유사 배열 객체(array-like-object)
var obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
Array.prototype.push.call(obj, 'd');
console.log(obj); // { 0: 'a', 1: 'b', 2: 'c', 3: 'd', length: 4 }
var arr = Array.prototype.slice.call(obj);
console.log(arr); // [ 'a', 'b', 'c', 'd' ]
Array.from
// 유사배열
var obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
// 객체 -> 배열
var arr = Array.from(obj);
console.log(arr); // [ 'a', 'b', 'c' ]
bind 메소드
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // 전역 객체 1 2 3 4
// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 }); // 즉시 호출x
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8
// 부분 적용 함수 구현
var bindFunc2 = func.bind({ x: 1 }, 4, 5); // 4와 5를 미리 적용
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
bindFunc2(8, 9); // { x: 1 } 4 5 8 9
상위 컨텍스트의 this를 내부 함수나 콜백 함수에 전달
내부 함수
우회법보다 call/apply/bind를 사용
var obj = {
outer: function () {
console.log(this); // obj
//var self = this; 사용 지양
var innerFunc = function () {
console.log(this);
};//.bind(this) // this를 결합한 새 함수 할당
// call을 이용해서 this 전달
innerFunc.call(this); // obj
}
};
obj.outer();
콜백 함수
setTimeout(this.logThis, 1000); // this 유실
setTimeout(this.logThis.bind(this), 1000); // this binding
화살표 함수의 예외 사항
var obj = {
outer: function () {
console.log(this); // obj
var innerFunc = () => {
console.log(this); // obj
};
innerFunc();
}
};
obj.outer();