
this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수임.
this는 JS엔진에 의해 암묵적으로 생성되며, 코드 어디서든 참조가 가능. 함수를 호출하게 되면 arguments 객체와 this가 암묵적으로 함수 내부에 전달됨.
this가 가리키는 값(this 바인딩)은 함수 호출 방식에 의해 동적으로 결정됨.
// 생성자 함수
function Circle(radius) {
// this는 생성자 함수가 생성할 인스턴스를 가리킴
this.radius = radius;
}
Circle.prototype.getDiameter = function () {
// this는 생성자 함수가 생성할 인스턴스를 가리킴
return 2 * this.radius;
}
// 인스턴스 생성
const circle = new Circle(5);
console.log(circle.getDiameter()); // 10
// this 바인딩은 함수 호출 방식에 따라 동적으로 결정됨
const foo = function () {
console.dir(this);
};
// 1. 일반 함수 호출
foo(); // window
// 2. 메서드 호출
const obj = { foo };
obj.foo(); // obj
// 3. 생성자 함수 호출
new foo(); // foo {}
기본적으로 this에는 전역 객체가 바인딩 됨.
function foo() {
console.log("foo's this: ", this); // window
function bar() {
console.log("bar's this: ", this); // window
}
bar();
}
foo();
strict mode가 적용된 일반 함수 내부의 this에는 undefined가 바인딩됨.
function foo() {
'use strict';
console.log("foo's this: ", this); // undefined
function bar() {
console.log("bar's this: ", this); // undefined
}
bar();
}
foo();
일반 함수로 호출된 모든 함수(중첩 함수, 콜백 함수 포함) 내부의 this에는 전역 객체가 바인딩 됨.
var value = 1;
const obj = {
value: 100,
foo() {
console.log("foo's this: ", this); // {value: 100, foo: ⨍}
// 콜백 함수 내부의 this에는 전역 객체가 바인딩 됨
setTimeout(function () {
console.log("callback's this: ", this); // window
console.log("callback's this.value", this.value); // 1
}, 100);
}
};
obj.foo();
화살표 함수 내부의 this는 상위 스코프의 this를 가리킴
var value = 1;
const obj = {
value: 100,
foo() {
// 화살표 함수 내부의 this는 상위 스코프의 this를 가리킴
setTimeout(() => console.log(this.value), 100); // 100
}
};
메서드 내부의 this는 메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩 됨.
const person = {
name: 'Lee',
getName() {
// 메서드 내부의 this는 메서드를 호출한 객체에 바인딩됨
return this.name;
}
};
// 메서드 getName을 호출한 객체는 person임
console.log(person.getName()); // Lee
const anotherPerson = {
name: 'Kim'
};
// getName 메서드를 anotherPerson 객체의 메서드로 할당
anotherPerson.getName = person.getName;
// getName 메서드를 호출한 객체는 anotherPerson
console.log(anotherPerson.getName()); // Kim
// getName 메서드를 변수에 할당
const getName = person.getName;
// getName 메서드를 일반 함수로 호출
console.log(getName()); // ''
프로토타입 메서드 내부에서 사용된 this도 일반 메서드와 마찬가지로 해당 메서드를 호출한 객체에 바인딩 됨.
function Person(name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
};
const me = new Person('Lee');
// getName 메서드를 호출한 객체는 me
console.log(me.getName()); // Lee
Person.prototype.name = 'Kim';
// getName 메서드를 호출한 객체는 Person.prototype
console.log(Person.prototype.getName()); // Kim
생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩됨.
// 생성자 함수
function Circle(radius) {
// 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킴
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
// 반지름 5인 Circle 객체를 생성
const circle1 = new Circle(5);
// 반지름 10인 Circle 객체를 생성
const circle2 = new Circle(10);
console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20
apply, call, bind 메서드는 Function.prototype의 메서드임.(모든 함수가 상속받아 사용 가능)
const user = { name: "현석" };
function greet(greeting, punctuation) {
// 원래라면 this는 전역 객체(window)겠지만, call/apply/bind로 user를 가리키게 함
console.log(`${greeting}, ${this.name}${punctuation}`);
}
// 1. call 사용 (인수를 쉼표로 나열하여 즉시 실행)
greet.call(user, "안녕하세요", "!");
// 출력: "안녕하세요, 현석!"
// 2. apply 사용 (인수를 배열로 묶어 전달하며 즉시 실행)
greet.apply(user, ["반갑습니다", "!!"]);
// 출력: "반갑습니다, 현석!!"
// 3. bind 사용 (this가 바인딩된 '새로운 함수'를 반환, 즉시 실행 X)
const boundGreet = greet.bind(user);
// 원하는 시점에 호출 (인수는 이때 전달하거나, bind 시 미리 전달 가능)
boundGreet("어서오세요", "...");
// 출력: "어서오세요, 현석..."