-
Section 12. 자바스크립트 this의 동적 바인딩자바스크립트 2023. 4. 7. 17:50
I. this - "이곳의~"
- 기본적으로 자신이 속한 곳을 가리킨다.
- 함수의 호출 방식에 따라 가리키는 바가 달라진다. - 자바스크립트 특성
1. 전역에서의 this
- 브라우저의 콘솔창 : window 객체 - globalThis와 같음
- Node.js의 REPL: global 객체 - globalThis와 같음
- .js 문서로 작성 후 실행 - 빈 객체가 나온다.
- 이유는 Node.js에서 각 .js문서들은 모듈로서 실행되기 때문이다.
2. 함수 안에서의 this
느슨한 모드와 엄격 모드에서 다르게 동작한다.
function func () { console.log(this); // globalThis } func(); //Window 객체
'use strict'; function func () { console.log(this); // undefined } func(); //undefined
객체에 속하지 않은 함수에서는 this 사용이 의미 없다.
3. 객체 안에서의 this
a. 객체 리터럴 - 해당 객체를 가리킨다.
const obj = { x: 123, getX: function () { return this.x; } } console.log(obj.getX()); //123
b. 생성자 함수 - 생성될 인스턴스를 가리킨다.
function Person (name, age) { this.name = name; this.age = age; this.introduce = function () { return `저는 ${this.name}, ${this.age}세입니다.` } } console.log( new Person('홍길동', 20).introduce() ); //저는 홍길동, 20세입니다.
c. 클래스 선언 - 생성될 인스턴스를 가리킨다.
class KangChicken { constructor (name, no) { this.name = name; this.no = no; } introduce () { return `안녕하세요, ${this.no}호 ${this.name}점입니다!`; } } console.log( new KangChicken('강남', 17).introduce() );
II. 동적 바인딩
- 자바스크립트의 독특한 동작방식이다.
- this가 가리키는 대상이 함수의 호출 주체 또는 그 방식에 따라 달라진다.
const korean = { favorite: '김치', makeStew: function (isHot, pots) { return `${isHot ? '매운' : '순한'} ${this.favorite}찌개 ${pots}냄비`; } }; const italian = { favorite: '피자' };
console.log( korean.makeStew(true, 1) ); //매운 김치찌개 1냄비
만약 makeStew프로퍼티를 italian에게 할당을 하면 다음과 같다
// 이탈리아인에게 한국인이 찌개 끓이는 법을 알려줌 italian.makeStew = korean.makeStew; console.log( italian.makeStew(false, 2) ); //순한 피자찌개 2냄비
같은 this를 썻지만 this가 가리키는 것이 korean에서 italian으로 바뀐 것을 볼 수 있다.
함수가 누가, 어떻게 호출되었는가에 따라 this가 가리키는 대상이 달라진다.
해결방법들
1. call를 사용한 함수 호출
this의 대상과 인자들을 나열한다.
console.log( italian.makeStew.call(korean, false, 2) ); //순한 김치찌개 2냄비
2. apply를 사용한 함수 호출
this의 대상 뒤의 인자들을 배열로 넣어준다.
console.log( italian.makeStew.apply(korean, [false, 2]) ); //순한 김치찌개 2냄비
3. bind를 사용한 this 대상을 고정한다.
this의 대상이 동적으로 변하지 않는 함수를 반환한다.
// ⭐ this가 바인딩된 새 함수를 만듦 italian.makeRightStew = korean.makeStew.bind(korean); console.log( italian.makeRightStew(false, 2) );
추가 인자들까지 바인딩이 가능하다
italian.makeClassicStew = korean.makeStew.bind(korean, true, 1); console.log( italian.makeClassicStew() ); //매운 김치찌개 1냄비
4. 바인딩된 함수를 내보내는 함수
const korean = { favorite: '김치', makeStew: function (isHot, pots) { return `${isHot ? '매운' : '순한'} ${this.favorite}찌개 ${pots}냄비`; }, teachMakingStew: function () { return this.makeStew.bind(this); } }; const italian = { favorite: '피자' };
italian.makeStew = korean.teachMakingStew(); console.log( italian.makeStew(false, 2) ); //순한 김치찌개 2냄비
5. 생성자 함수일 경우 - 함수 자체를 미리 인스턴스에 바인딩하기
function Korean () { this.favorite = '김치'; this.makeStew = function (isHot, pots) { return `${isHot ? '매운' : '순한'} ${this.favorite}찌개 ${pots}냄비`; }; // 💡 여기서 바인딩을 고정시켜버림 this.makeStew = this.makeStew.bind(this); } function Italian () { this.favorite = '피자'; }
const korean = new Korean(); const italian = new Italian(); italian.makeStew = korean.makeStew; console.log( italian.makeStew(false, 2) ); //순한 김치찌개 2냄비
배열 메서드의 thisArg
- 콜백으로 주어진 함수 내에서 this가 가리킬 대상.
- 보통 콜백함수 다음 인자로 넣는다.
function recommendForYou (me) { const products = [ { sex: 'F', size: 'M' }, { sex: 'M', size: 'L' }, { sex: 'F', size: 'M' }, { sex: 'U', size: 'S' }, { sex: 'M', size: 'L' }, { sex: 'F', size: 'S' }, ]; products .map((itm, idx) => { return { ...itm, idx } }) // ⚠️ 화살표 함수 대신 function 선언 함수 사용 주목 .filter(function ({sex, size}) { return ['U', this.sex].includes(sex) && size === this.size }, me) // 💡 thisArg .forEach(function ({idx}) { console.log(`${this.name}님, ${++idx}번은 어떠세요?`); }, me); // 💡 thisArg }
const peter = { name: '피터', sex: 'M', size: 'L' }; const jane = { name: '제인', sex: 'F', size: 'S' };
recommendForYou(peter); recommendForYou(jane); //피터님, 2번은 어떠세요? //피터님, 5번은 어떠세요? //제인님, 4번은 어떠세요? //제인님, 6번은 어떠세요?
'자바스크립트' 카테고리의 다른 글
Section 13. 자바스크립트 프로토타입의 개념 (0) 2023.04.08 Section 12. 자바스크립트 this의 정적 바인딩 (0) 2023.04.07 Section 12. 자바스크립트 렉시컬과 클로저 (0) 2023.04.07 Section 11. 자바스크립트 옵셔널 체이닝 (0) 2023.04.07 Section 11. 자바스크립트 엄격 모드 (0) 2023.04.07