-
22장. this책/모던 자바스크립트 딥다이브 2022. 5. 9. 22:34
22장. this
22-1. this 키워드
function Circle(radius) { // 이 시점에는 생성자 함수 자신이 생성할 인스턴스를 가리키는 식별자 모름. ????.radius = radius; } Circle.prototype.getDiameter = function() { // 이 시점에는 생성자 함수 자신이 생성할 인스턴스를 가리키는 식별자 모름. return 2 * ????.radius; } const circle = new Circle(5);
- 생성자 함수를 정의하는 시점에는 아직 인스턴스 생성 이전이므로 생성할 인스턴스를 가리키는 식별자를 알 수 없다. 따라서 자신이 속한 객체 또는 생성할 인스턴스를 가리키는 특수한 식별자가 필요한데 이를 위해 JS는 this 라는 특수한 식별자를 제공한다.
- this 는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수(self-referencing variable)이다.
- this 를 통해서 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.
- this 는 JS 엔진에 의해 암묵적 생성, 어디서든 참조 가능하다.
- 함수 호출시 arguments 객체와 this 가 암묵적으로 함수 내부에 전달된다.
- this 가 가리키는 값, 즉 this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.
// 객체 리터럴 메서드 내부의 this는 메서드를 호출한 객체를 가리킨다. const circle = { radius: 5, getDiameter() { return 2 * this.radius; } } // 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다. function Circle(radius) { this.radius = radius; } Circle.prototype.getDiameter = function() { return 2 * this.radius; }
22-2. 함수 호출 방식과 this 바인딩
const foo = function() { console.dir(this); }; // 일반 함수 호출 foo(); // window // 메서드 호출 const obj = { foo }; obj.foo(); // obj // 생성자 함수 호출 new foo(); // foo {} // 간접 호출 const bar = { name: 'bar' }; foo.call(bar); foo.apply(bar); foo.bind(bar);
일반 함수 호출
- 기본적으로 this 에는 전역 객체가 바인딩된다.
- 어떠한 함수라도 일반 함수로 호출되면 this에 전역 객체가 바인딩 된다.
// 일반 function foo() { console.log(this); // window function bar() { console.log(this); // window } bar(); } foo(); // strict mode function foo() { 'use strict'; console.log(this); // undefined function bar() { console.log(this); // undefined } bar(); } foo();
var value = 1; const obj = { value: 100, foo() { console.log(this); // { value: 100, foo: f } console.log(this); // 100 function bar() { console.log(this); // window console.log(this); // 1 } // 메서드 내에서 정의한 중첩 함수도 일반 함수로 호출되면 중첩 함수 내부의 this에는 // 전역 객체가 바인딩된다. bar(); } }; obj.foo();
var value = 1; const obj = { value: 100, foo() { console.log(this); // { value: 100, foo: f } // 콜백 함수 내부의 this에는 전역 객체가 바인딩된다. setTimeout(function() { console.log(this); // window console.log(this); // 1 }, 100); } }; obj.foo();
- 메서드 내부의 중첩 함수나 콜백 함수의 this 바인딩을 메서드의 this 바인딩과 일치시키기 위한 방법
// 1. 따로 변수 만들어 바인딩 var value = 1; const obj = { value: 100, foo() { // this 바인딩(obj)을 변수 that 에 할당 const that = this; // 콜백 함수 내부에서 this 대신 that 을 참조한다. setTimeout(function() { console.log(that.value); // 100 }, 100); } }; obj.foo(); // 2. Function.prototype.apply, call, bind 사용하여 명시적 바인딩 var value = 1; const obj = { value: 100, foo() { // 콜백 함수에 명시적으로 this를 바인딩한다. setTimeout(function() { console.log(this.value); // 100 }.bind(this), 100); } }; obj.foo(); // 3. 화살표 함수 사용하여 바인딩 var value = 1; const obj = { value: 100, foo() { // 화살표 함수 내부의 this는 상위 스코프의 this를 가리킨다. setTimeout(() => console.log(this.value), 100); // 100 } }; obj.foo();
메서드 호출
- 메서드 내부의 this에는 메서드를 호출한 객체, 즉 메서드를 호출할 때 메서드 이름 앞의 . 연산자 앞에 기술한 객체가 바인딩 된다.
// 1 const anotherPerson = { name: 'Lee' }; anotherPerson.getName = person.getName; console.log(anotherPerson.getName()); // Lee // 2 const getName = person.getName; console.log(getName()); // '' -> 브라우저 환경 '', Node환경 undefined
// 프로토타입 메서드 내부에서 사용된 this도 일반 메서드와 마찬가지 function Person(name) { this.name = name; } Person.prototype.getName = function() { return this.name; }; const me = new Person('Lee'); console.log(me.getName()); // Lee Person.prototype.name = 'Kim'; console.log(Person.prototype.getName()); // Kim
생성자 함수 호출
- 생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩 된다.
Function.prototype.apply/call/bind 메서드에 의한 간접 호출
- apply, call, bind 메서드는 Function.prototype의 메서드여서 모든 함수가 상속받아 사용할 수 있다.
function getThisBinding() { return this; } const thisArg = { a: 1 }; console.log(getThisBinding()); // window console.log(getThisBinding.apply(thisArg)); // { a: 1 } console.log(getThisBinding.call(thisArg)); // { a: 1 }
정리
함수 호출 방식 this 바인딩
일반 함수 호출 전역 객체 메서드 호출 메서드를 호출한 객체 생성자 함수 호출 생성자 함수가 생성할 인스턴스 Function.prototype.apply/call/bind 메서드에 의한 간접 호출 메서드에 첫 번째 인수로 전달한 객체 '책 > 모던 자바스크립트 딥다이브' 카테고리의 다른 글
45장. 프로미스 (3) 2022.05.14 44장. REST API (0) 2022.05.14 19장. 프로토타입 (0) 2022.04.30 18장. 함수와 일급 객체 (2) 2022.04.24 17장. 생성자 함수에 의한 객체 생성 (0) 2022.04.24