22. this
1. this 키워드
- 메서드가 자신이 속한 객체의 프로퍼티를 참조하려면 자신이 속한 객체를 가리키는 식별자를 참조할 수 있어야 한다.
- 객체 리터럴 방식의 경우 메서드 내부에서 식별자를 재귀적으로 참조할 수 있다.
- 생성자 함수 방식의 경우 생성자 함수를 정의하는 시점에서는 아직 인스턴스를 생성하기 전이므로 인스턴스를 가리키는 식별자를 알 수 없다.
this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기참조변수다.
⇒ this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.
- 함수를 호출하면 arguments 객체와 this가 암묵적으로 함수 내부에 전달된다.
- 단, this가 가리키는 값, 즉 this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.
** 바인딩? 식별자와 값을 연결하는 과정
2. 함수 호출방식과 this 바인딩
자바스크립트에서 this 바인딩은 함수의 호출 시점에 따라 동적으로 결정된다
- 1. 일반함수 호출
- 일반함수로 호출된 모든 함수(중첩함수, 콜백함수 포함) 내부의 this에는 전역 객체(
window)
가 바인딩된다. - strict 모드가 적용된 일반 함수 내부의 this에는
undefined
가 바인딩된다 - 하지만, 메서드 내의 중첩함수 또는 콜백함수의 this가 외부함수의 this와 일치하지 않는 것은 헬퍼함수로서 동작을 어렵게 한다.
Function.prototype.apply
Function.prototype.call
Function.prototype.bind
로 명시적으로 this를 일치시킬 수 있다- 화살표 함수를 사용해서 this를 일치시킬 수 있다
- ( 화살표 함수는 자신만의 this를 갖지 않기 때문에 lexical scope를 갖게 된다. 그래서, 화살표 함수 내부의 this는 상위 스코프의 this를 가리킨다 )
- 일반함수로 호출된 모든 함수(중첩함수, 콜백함수 포함) 내부의 this에는 전역 객체(
- 2. 메서드 호출
- 점 연산자를 통해 객체의 메서드로서 호출되는 함수의 내부에서 this는 점 연산자(.) 앞에 있는 객체에 바인딩된다.
- 이를 암묵적 바인딩이라고 부른다.
const person = { name: 'Lee', getName() { return this.name; } } console.log(person.getName()); //Lee
getName
메서드는person
객체에 포함된 것이 아니라 독립적으로 존재하는 별도의 객체다.그저(새롭게 알게 됨!! 흥미돋!!)getName
프로퍼티가 함수 객체를 가리키고 있을 뿐이다. ⇒ 그렇기 때문에 this는 메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩되는 것인가??- 그래서
getName
프로퍼티가 가리키는 함수객체, 즉getName
메서드는 다른 객체의 메서드도 될 수 있고, 일반 변수에 할당해서 일반함수로 호출될 수 있다. const anoterPerson = { name: "kim" } anotherPerson.getName = person.getName // this는 anotherPerson const getName = person.getName // this는 window
- 프로토타입 메서드 내부에서 사용되는 this도 일반 메서드와 마찬가지로 호출한 객체에 바인딩된다.
- 3. 생성자 함수 호출
- new 연산자와 함께 호출되는 경우 함수는 생성자로써 호출된다
- 생성자 함수 내부에서 this는 생성할 객체를 의미한다.
// 생성자 함수 function Person(name) { this.name = name; } var me = new Person('Lee'); console.log(me); // Person {name: "Lee"} // new 연산자와 함께 생성자 함수를 호출하지 않으면 생성자 함수로 동작하지 않는다. var you = Person('Kim'); console.log(you); // undefined
- 4. Function.prototype~ 객체의 메서드에 의한 간접호출
Function~~
객체는 this를 명시적으로 바인딩할 수 있는 메서드를 제공한다.- apply, call
- this로 사용할 객체와 인수 리스트를 인수로 전달받아 함수를 호출한다
- 본질적인 기능은 함수를 호출하는 것이다. 함수를 호출하면서 첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩한다.
- 대표적인 용도는 arguments 객체와 같은 유사배열객체에
Array.prototype.slice
같은 배열 메서드를 사용하는 경우다. function convertArgsToArray() { console.log(arguments); // arguments 객체를 배열로 변환 // slice: 배열의 특정 부분에 대한 복사본을 생성한다. var arr = Array.prototype.slice.apply(arguments); // arguments.slice // var arr = [].slice.apply(arguments); console.log(arr); return arr; } convertArgsToArray(1, 2, 3); // [1,2,3]
- bind
- this로 사용할 객체로 this 바인딩이 교체된 함수를 새롭게 생성해 반환한다.
- apply와 call 과 달리 함수를 호출하지 않으므로 명시적으로 호출해야 한다.
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 Function.prototype.call Function.prototype.bind 메서드에 의한 간접 호출 | Function.prototype.apply Function.prototype.call Function.prototype.bind 메서드에 첫번째 인수로 전달한 객체 |
추가1 : this 바인딩 우선순위
new 연산자에 의한 바인딩 > 명시적 바인딩 > 암시적 바인딩 > 일반함수 호출에 의한 바인딩
- bind 메서드에 의한 바인딩이 apply, call에 의한 바인딩보다 우선순위가 높다
- apply, call, bind 실행 시 이를 호출한 함수가 화살표 함수면 첫번째 인자인 thisArg가 무시된다. (화살표 함수는 자신만의 this, argument가 없기 때문에 자신의 lexical scope인 window가 this가 된다. )
const person = {
name: "Lee",
foo(callback) {
setTimeout(callback.bind(this), 100);
},
};
person.foo(() => {
console.log(`Hi! my name is ${this.name}`);
});
// window.name은 빌트인 프로퍼티로 ""이다.
// Hi! my name is
'엘리스 ai 트랙 > FE' 카테고리의 다른 글
Javascript - ES11 ( ES2020 )의 특징들 (0) | 2022.04.04 |
---|---|
CI와 CD (0) | 2022.03.31 |
http 1.1 과 http 2 의 차이점 (0) | 2022.03.31 |
HTTP (0) | 2022.03.13 |
기본값+rest+spread (0) | 2022.03.07 |