
const circle = {
// 프로퍼티
radius: 5,
// 메서드
getDiameter() {
return 2*circle*radius;
}
};
console.log(circle.getDiameter());
function Circle(radius) {
// 아직 생성자 함수 자신이 생성할 인스턴스를 가리키는 식별자를 알 수 없다.
???.radius = radius;
}
Circle.prototype.getDiameter = function () {
// 아직 생성자 함수 자신이 생성할 인스턴스를 가리키는 식별자를 알 수 없다.
return 2 * ???.radius;
};
const circle = new Circle(5);
this 바인딩
- 바인딩이란?
- 식별자와 값을 연결
- ex) 변수선언에서 변수이름과 메모리 공간의 주소를 바인딩
- this 바인딩은 this와 this가 가리킬 객체를 바인딩하는 것!
// 전역
console.log(this); // window (전역 객체 window)
function square(number) {
// 일반 함수
console.log(this); // window (전역 객체 window)
}
square(2)
const person = {
name: 'Lee',
getName() {
// 메서드 내부
console.log(this); // {name:"Lee", getName:f} (메서드를 호출한 객체)
return this.name;
}
}
console.log(person.getName());
function Person(name) {
this.name = name;
// 생성자 함수 내부
console.log(this); // Person {name:"Lee"} (생성자 함수가 생성할 인스턴스)
}
const me = new Person('Lee');
🤔
일반함수로 호출된 모든 함수(중첩함수, 콜백함수 포함) 내부의 this에는
전역 객체가 바인딩!
- 메서드 내에서 정의한 중첩함수 도 일반 함수로 호출되면 내부의 this에는 전역 객체가 바인딩!
- 콜백함수가 일반 함수로 호출되면 콜백 함수 내부의 this에도 전역 객체가 바인딩!
🤔
하지만 보통 외부함수를 돕는 중첩함수와 콜백함수가
외부 함수의 this와 일치하지 않는 문제는 어떡하지??
var value = 1;
const obj = {
value: 100,
foo() {
// this 바인딩을 변수 that에 할당!
const that = this;
// 콜백 함수 내부에서 this 대신 that을 참조
setTimeout(function() {
console.log(that.value); // 100
}, 100);
}
};
obj.foo()
var value = 1;
const obj = {
value: 100,
foo() {
setTimeout(function() {
console.log(this.value);
}.bind(this), 100);
}
};
obj.foo();
var value = 1;
const obj = {
value: 100,
foo() {
// 화살표 함수 내부의 this는 상위 스코프의 this를 가리킨다.
setTimeout(() => console.log**(this.value)**, 100);
}
};
obj.foo();
const anotherPerson = {
name: 'Kim'
};
// getName을 anotherPerson 객체의 메서드로 할당 (다른 객체의 메서드)
anotherPerson.getName = person.getName;
// anotherPerson이 getName 메서드를 호출
console.log(anotherPerson.getName());
// getName 메서드를 변수에 할당
const getName = person.getName;
// 일반 함수로 getName 메서드를 호출
console.log(getName()); // ''
// 일반 함수로 호출된 getname 함수 내부의 this.name은 브라우저 환경에서 window.name과 같다.
function Perosn(name) {
this.name = name;
}
Perosn.prototype.getANme = function () {
return this.name;
};
const me = new Person('Lee');
console.log(me.getName()); // Lee
Person.prototype.name = 'Kim';
console.log(Person.prototype.getName()); // Kim
(그림 좀 더 이해해보기)
function Circle(radius) {
// 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
this.radius = radius;
this.getDiameter = function () {
return 2 * this.radius;
};
}
const circle1 = new Circle(5);
const circle2 = new Circle(10);
console.log(circle1.getDiameter());
console.log(circle2.getDiameter());
// new 연산자와 호출하지 않음 (이건 그냥 일반 함수 호출임...)
const circle3 = Circle(15);
// 일반 함수로 호출된 Circle에는 반환문이 없으므로 암묵적으로 undefined를 반환한다.
console.log(circle3); // undefined
// 일반 함수로 호출된 Circle 내부의 this는 전역 객체를 가리킨다.
console.log(radius); // 15Function.prototype.apply(thisArg[, argsArray])
주어진 this 바인딩과 인수 리스트 배열을 사용하여 함수를 호출한다.
Function.prototype.call(thisArg[, arg1[, arg2[. ...]]])
주어진 this 바인딩과 ,로 구분된 인수 리스트를 사용하여 함수를 호출한다.
function getThisBinding() {
console.log(arguments);
return this;
}
// this로 사용할 객체
const thisArg = {a : 1};
// getThisBinding 함수를 호출하면서 인수로 전달한 객체를
// getThisBinding 함수의 this에 바인딩한다.
// apply 메서드는 호출할 함수의 인수를 배열로 묶어 전달한다.
console.log(getThisBinding.apply(thisArg, [1,2,3]));
// call 메서드는 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달한다.
console.log(getThisBinding.call(thisArg, 1, 2, 3));
🤔 apply, call 메서드는 언제 쓸까?
- arguments 객체와 같은 유사 배열 객체에 배열 메서드를 사용하는 경우!
- 유사 배열 객체는 Array.prototype.slice같은 배열 메서드를 사용할 수 없으니까!
function convertArgsToArray() {
console.log(arguments);
// arguments 객체를 배열로 변환 (slice를 인수없이 호출하면 배열의 복사본을 생성한다.)
const arr = Array.prototype.slice.call(arguments);
// const arr = Array.prototype.slice.apply(arguments);
console.log(arr);
return arr;
}
convertArgsToArray(1,2,3);
function getThisBinding() {
return this;
}
// this로 사용할 객체
const thisArg = {a : 1};
console.log(getThisBinding.bind(thisArg));
// bind 메서드는 함수를 호출하지는 않으므로 명시적으로 호출해야한다.
console.log(getThisBinding.bind(thisArg)());
🤔 bind 메서드는 언제 쓸까?
- 메서드의 this와 메서드 내부의 중첩 함수 또는 콜백 함수의 this가 불일치하는 문제 해결!!
const person = {
name: 'Lee',
foo(callback) {
setTimeout(callback, 100);
}
};
person.foo(function () {
console.log(`Hi my name is ${this.name}.`); // Hi my name is .
}
전역 객체 window를 가리킨다.‘’.undefined.const person = {
name: 'Lee',
foo(callback) {
setTimeout(callback.bind(this), 100);
}
};
person.foo(function () {
console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
});
| 함수 호출 방식 | this 바인딩 |
|---|---|
| 일반 함수 호출 | 전역 객체 |
| 메서드 호출 | 메서드를 호출한 객체 |
| 생성자 함수 호출 | 생성자 함수가 생성할 인스턴스 |
| Function.prototype.apply/call/bind 메서드에 의한 간접 호출 | Function.prototype.apply/call/bind메서드에 첫번째 인수로 전달한 객체 |