this : 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수
다.
this 를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.
this 는 자바스크립트 엔진에 의해 암묵적으로 생성된다.
[ 💡 this 바인딩 ]
+ 바인딩(binding) : 식별자와 값을 연결하는 과정
+ this 바인딩 : this와 this가 가리킬 객체를 바인딩하는 것
"메소드를 호출한 객체"
이다.const circle = {
radius : 5,
getDiameter() {
// 여기서 this는 메소드를 호출한 객체
return 2 * this.radius;
}
}
console.log(circle.getDiameter()); // 10
"생성자 함수가 생성할 인스턴스"
다// 생성자 함수
function Circle(radius) {
// 여기서 this는 생성자 함수 Circle이 생성할 인스턴스
this.radius = radius;
}
Circle.prototype.getDiameter = function () {
// 여기서 this는 생성자 함수가 생성할 인스턴스
return 2 * this.radius;
};
// 인스턴스 생성
const circle = new Circle(5);
console.log(circle.getDiameter()); // 10
함수를 호출하는 방식
일반 함수 호출
메소드 호출
생성자 함수 호출
Function.prototype.apply / call / bind 메서드에 의한 간접 호출
기본적으로 this에는 "전역 객체(global object)"가 바인딩된다.
전역 함수는 물론 중첩 함수는 -> 일반 함수로 호출된 모든 함수 내부의 this에는 전역 객체가 바인딩
function foo() {
console.log(`전역 함수 foo의 this : ${this}`); // 전역 함수 foo의 this : [object global]
function bar() {
console.log(`중첩 함수 bar의 this : ${this}`); // 중첩 함수 bar의 this : [object global]
}
bar();
}
foo();
// strict mode 적용
function foo() {
("use strict");
console.log(`전역 함수 foo의 this : ${this}`); // 전역 함수 foo의 this : undefined
function bar() {
console.log(`중첩 함수 bar의 this : ${this}`); // 중첩 함수 bar의 this : undefined
}
bar();
}
foo();
// 전역 변수 value ( 전역 객체 프로퍼티 )
var value = 1;
const obj = {
value: 100,
foo() {
console.log(`foo 메서드의 this : ${this}`); // foo 메서드의 this : [object Object]
console.log(`foo 메서드의 this가 가리키는 객체의 value : ${this.value}`); // foo 메서드의 this가 가리키는 객체의 value : 100
// 메서드 내, 정의한 중첩 함수
function bar() {
console.log(`메서드 내 중첩 함수 bar의 this : ${this}`); // 메서드 내 중첩 함수 bar의 this : [object global]
console.log(`중첩 함수 bar의 this가 가리키는 객체의 value : ${this.value}`); // 중첩 함수 bar의 this가 가리키는 객체의 value : 1
}
// 메서드 내 중첩 함수를 일반 함수 처럼 호출
bar();
},
};
obj.foo();
// 전역 변수 value ( 전역 객체 프로퍼티 )
var value = 1;
const obj = {
value: 100,
foo() {
console.log(`foo 메서드의 this : ${this}`); // foo 메서드의 this : [object Object]
console.log(`foo 메서드의 this가 가리키는 객체의 value : ${this.value}`); // foo 메서드의 this가 가리키는 객체의 value : 100
// 메서드 내 콜백 함수
setTimeout(function () {
console.log(`callback 함수의 this : ${this}`); // callback 함수의 this : [object global]
console.log(`callback 함수의 this가 가리키는 객체의 value : ${this.value}`); // callback 함수의 this가 가리키는 객체의 value : 1
}, 100);
},
};
obj.foo();
중첩함수나 콜백함수의 경우 , 용도가 일반적으로 외부 함수를 돕는 헬퍼함수 역할을 한다.
메소드 내부의 중첩 함수나 콜백 함수의 this 바인딩을 메소드의 this 바인딩과 일치시키기 위한 방법
메소드의 this 바인딩할 객체를 변수에 할당하는 방법
Function.prototype.apply or Function.prototype.call 에 의한 바인딩
// 전역 변수 value ( 전역 객체 프로퍼티 )
var value = 1;
const obj = {
value: 100,
foo() {
// 콜백 함수에 바인딩할 obj 객체를 가리키는 this를 변수 that에 할당
const that = this;
setTimeout(function () {
console.log(`callback 함수의 this : ${that}`); // callback 함수의 this : [object Object]
console.log(`callback 함수의 this가 가리키는 객체의 value : ${that.value}`); // callback 함수의 this가 가리키는 객체의 value : 100
}, 100);
},
};
obj.foo();
// 전역 변수 value ( 전역 객체 프로퍼티 )
var value = 1;
const obj = {
value: 100,
foo() {
// Function.prototype.bind 메서드로 obj 객체를 가리키는 this를 콜백함수에 명시적으로 바인딩
setTimeout(
function () {
console.log(`callback 함수의 this : ${this}`); // callback 함수의 this : [object Object]
console.log(`callback 함수의 this가 가리키는 객체의 value : ${this.value}`); // callback 함수의 this가 가리키는 객체의 value : 100
}.bind(this),
100,
);
},
};
obj.foo();
기본적으로 메소드 내부의 this에는 메소드를 호출한 객체가 바인딩된다.
메소드를 호출할 때 메소드 앞에 마침표 연산자 앞에 기술한 객체가 바인딩된다.
const person = {
name : "WI",
getName() {
// 메서드 내부의 this는 메서드를 호출한 객체에 바인딩
// getName 메서드는 person 객체에 포함된 것이 아닌, 독립적으로 존재하는 별도의 객체 개념
return this.name;
}
}
console.log(person.getName()); // WI
메소드는 특정 객체에 포함된 것이 아닌, 독립적으로 존재하는 별도의 객체
다른 객체의 프로퍼티에 할당이 가능함.
일반 변수에 할당하여 일반 함수로 호출도 가능함
const person = {
name: "WI",
getName() {
// 메서드 내부의 this는 메서드를 호출한 객체에 바인딩
// getName 메서드는 person 객체에 포함된 것이 아닌, 독립적으로 존재하는 별도의 객체 개념
return this.name;
},
};
const anotherPerson = {
name : "Kim"
}
anotherPerson.getName = person.getName;
// getName 메소드를 --> anotherPerson 객체의 메서드로 할당
// getName을 호출한 객체는 이 시점에선 person이 아닌 anotherPerson이다.
console.log(anotherPerson.getName()); // KIM
// getName을 getName 변수에 할당 (getName 메서드는 독립적인 객체이기 때문)
const getName = person.getName;
// 생성자 함수
function Person(name) {
this.name = name;
}
// 프로토타입에 getName 메서드 할당
Person.prototype.getName = function () {
return this.name;
};
// me 인스턴스 생성
const me = new Person("WI");
// 이 시점에서 getName 메서드를 호출한 주체는 me 객체
console.log(me.getName()); // WI
Person.prototype.name = "KIM";
// 이 시점에서 getName 메서드를 호출한 주체는 Person.prototype 객체
console.log(Person.prototype.getName()); // KIM
// 생성자 함수
function Person(name) {
this.name = name;
this.getName = function () {
return `안녕하세요. 저는 ${this.name}입니다.`;
};
}
const person1 = new Person("WI");
const person2 = new Person("KIM");
console.log(person1.getName()); // 안녕하세요. 저는 WI입니다.
console.log(person2.getName()); // 안녕하세요. 저는 KIM입니다.
apply, call, bind 는 Function.prototype의 메소드이다.
모든 함수가 이 메소드들을 상속 받아서 사용 가능하다.
Function.prototype.apply(this로 사용할 객체, arguments 리스트(배열 or 유사배열객체))
Function.prototype.call(this로 사용할 객체, arguments 인수 리스트(,로 구분하여 전달))
Function.prototype.bind(this로 사용할 객체)
apply, call
const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);
console.log(max);
// Expected output: 7
const min = Math.min.apply(null, numbers);
console.log(min);
// Expected output: 2
function add(x, y) {
this.val = x + y;
console.log(this.val);
}
let obj = { val : 0 };
add.apply(obj, [2, 8]); // 10
add.call(obj, 2, 8); // 10
bind
본질적인 기능은 함수를 호출하진 않고 this로 사용할 객체만 전달
대표적으로, 메서드의 this와 메서드 내부의 중첩 함수 or 콜백 함수의 this가 불일치하는 문제 해결에 효과적
const person = {
name : "WI",
foo(callback) {
// bind를 적용하지 않는다면, foo 메소드 내부에 콜백 함수에 정의도니 this는 전역객체
// 전역 객체에는 name 프로퍼티가 없기 때문에, 원래는 undefined 를 출력하는 것이 맞다.
// 하지만, Function.prototype.bind 메서드로 콜백 함수의 주체를 person 객체로 동적 바인딩 해주었다.
setTimeout(callback.bind(this),100);
}
}
person.foo(function () {
console.log(`안녕하세요. ${this.name}입니다.`); // 안녕하세요. WI입니다.
});