자바스크립트에서 this 란 '나' 라는 단어와 비슷합니다. 어떤 문맥이냐에 따라서 그 의미(값)이 바뀜니다.
var name = 'window name';
function log() {
console.log(this.name); // 'this' is always an object
}
var obj = {
name: 'ken',
logName: log,
}
log(); // this : window ★★★ (window 객체에 의해 호출 - 내부적으로)
obj.logName(); // this : obj ★★★ (obj 객체에 의해 호출)
'this' 의 값은 'this' 를 사용하는 해당 함수를 "어떻게 실행"하느냐에 따라 바뀜니다.
(혼동 주의 : 호출된 변수 X!, 호출된 함수 O!)
함수를 실행하는 방법엔 크게 4가지가 있습니다.
(this 를 이용하는) 해당 함수를 이 4가지 중 어떤 방식으로 실행하느냐에 따라 this 의 값은 바뀜니다.
Regular function call : 일반 함수 실행 방식
function foo() {
console.log(this); *// 'this' === global object (브라우저상에선 window 객체)*
}
foo(); *// 일반 함수 실행 방식*
'use strict';
function foo() {
console.log(this); *// 'this' === undefined*
}
foo(); *// 일반 함수 실행 방식
// 'use strict' 사용 시 this -> undefined
// window.(변수 및 함수); 이렇게 window 라고 명시해 주어야 됨
// [ 보충 설명 ]
// var 나 function 은 global 객체인 window 객체에서 접근이 가능하나
// let, const 의 경우 window 객체에서 접근이 불가능하다.*
var age = 100;
function foo() {
var age = 99;
bar();
}
function bar() {
console.log(this.age);
}
foo(); *// 일반 함수 실행 방식*
*// (this.age === 100 / this === window)*
Dot Notation - 점 방식 (함수 실행 시 점 앞의 객체가 this)
var age = 100;
var ken = {
age: 35,
foo: function () {
console.log(this.age);
},
too: this,
};
ken.foo(); *// 객체 실행 방식 (this.age === 35 / this === ken)*
console.log(ken.too); *// (this === window) 변수는 X, 함수만 O
// 변수의 this 가 해당 객체일 때에는 new 로 객체를 생성하였을 때
// 즉, 생성자 함수와, 클래스 함수에서 변수의 this 는 해당 객체임*
function foo() {
console.log(this.age);
}
var age = 100;
var ken = {
age: 35,
foo,
};
var wan = {
age: 31,
foo,
};
ken.foo(); *// 객체 실행 방식 (this.age === 35 / this === ken)*
wan.foo(); *// 객체 실행 방식 (this.age === 31 / this === wan)*
var age = 100;
var ken = {
age: 35,
foo: function () {
console.log(this.age);
},
};
var wan = {
age: 31,
foo: ken.foo,
};
var foo = ken.foo;
ken.foo(); *// 객체 실행 방식 (this.age === 35 / this === ken)*
wan.foo(); *// 객체 실행 방식 (this.age === 35 / this === wan)*
foo(); *// 일반 함수 실행 방식 (this.age === 100 / this === window)*
Function.prototype.call, Function.prototype.apply, Function.prototype.bind
function foo(a, b) {
console.log(this.age);
console.log(arguments);
console.log(a, b);
}
var age = 100;
var ken = {
age: 35,
foo,
};
var wan = {
age: 31,
foo,
};
*// call 과 apply 는 바로 선언하여 사용한다.*
foo.call(ken, [1, 2, 3, 4, 5], 1); *// (this.age === 35 / this === ken)*
foo.apply(wan, [1, 2, 3, 4, 5]); *// (this.age === 31 / this === wan)
//* console.log(arguments)
*// => 0: [1, 2, 3, 4, 5] / 1: 1
//* console.log(arguments)
*// => 0: 1/ 1: 2/ 2: 3/ 3: 4/ 4: 5
//* console.log(a, b);
*// [1, 2, 3, 4, 5] 1
//* console.log(a, b);
// 1 2
*// bind 는 변수에 할당하여 사용한다.*
var bar = foo.bind(ken, 10, 11);
bar(); *// (this.age === 35 / this === ken)
// ----------------------------
// bind 다른 예
const bindTest = { name: 'ht' };
function bindFunc() {
console.log(this.name);
}
const result = bindFunc.bind(bindTest);
result();
// ht
bindFunc.bind(bindTest)();
// ht*
[ call ] → 함수를 호출
call(this: Function, thisArg: any, ...argArray: any[]): any;
현재 객체를 다른 객체로 대체하여 객체의 메서드를 호출합니다.
@param thisArg 는 현재 개체로 사용할 개체입니다.
@param argArray 는 메서드에 전달할 인수 목록입니다. → (인수 목록)
[ apply ] → 함수를 호출
apply(this: Function, thisArg: any, argArray?: any): any;
지정된 객체를 함수의 this 값으로, 지정된 배열을 함수의 인수로 대체하여 함수를 호출합니다.
@param thisArg 는 this 객체로 사용할 객체.
@param argArray 는 함수에 전달할 인수 집합입니다. → (인수 집합)
[ bind ] → 함수문 반환
bind(this: Function, thisArg: any, ...argArray: any[]): any;
주어진 함수에 대해 원래 함수와 본문이 동일한 바인딩된 함수를 만듭니다.
바인딩된 함수의 this 개체는 지정된 개체와 연결되며 지정된 초기 매개변수를 갖습니다.
@param thisArg 는 this 키워드가 새 함수 내에서 참조할 수 있는 개체입니다.
@param argArray 는 새 함수에 전달할 인수 목록입니다. → (인수 목록)
※ 즉 해당 [함수]를 해당 [객체]로 바인딩 한다. 는 의미이다.
함수.call(바인딩할 객체, 인수, ...);
함수.apply(바인딩할 객체, 인수, ...);
함수.bind(바인딩할 객체, 인수, ...);
'new' keyword
*// 생성자 함수*
function Foo() {
*//this = {}; (내부적으로 동작)*
console.log(this);
this.name = this;
*//return this; (내부적으로 동작)*
}
new Foo(); *// new Foo() 선언 시 this 에 Foo 객체 할당
// this === Foo*
생성자 함수와 마찬가지로, 클래스 함수에서도 this = {} / return this 처럼 동일하다.
예외 (Event Handler)
const element = document.querySelector('#vanila');
element.addEventListener('click', function onClick (event) {
console.log(this); // 지양(헷갈리게 만든다)
console.log(event.target); // 지향(상황에 따라)
console.log(event.currentTarget); // 지향(상황에 따라)
});
문제)
예제( class 에서 this → 생성자 함수와 동일 )
class Counter {
count = this;
increase = function () {
console.log(this);
};
increase2 = () => { // bind 방법2 (Arrow function 사용)
console.log(this);
};
}
const counter = new Counter();
console.log(counter.count); // this -> Counter
counter.increase(); // this -> Counter
const caller = counter.increase;
caller(); // this -> undefined
const caller2 = counter.increase.bind(counter); // bind 방법1 (bind 함수 사용)
caller2(); // this -> Counter
const caller3 = counter.increase2;
caller3(); // this -> Counter
class Bob { }
const bob = new Bob();
bob.run = counter.increase;
bob.run(); // this -> Bob