[240328] 21장 this

21장 this

this 키워드

  • 객체 리터럴은 재귀적으로 가능하지만 일반적이지 않다
    • 생성자 함수는 new 시점에서 인스턴스가 생성되는데, 그 동안 생성자 함수에서 식별자를 알 수 없다.
  • this 는 자신이 속한 객체 , 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다.
  • this 는 자바스크립트 엔진에 의해 암묵적으로 생성되며, 코드 어디서든 참조할 수 있다.
  • 함수를 호출하면 arguments 객체와 this 가 암묵적으로 함수 내부에 전달된다.
    • 지역변수처럼 사용 가능
  • this 가 가리키는 값, 즉 this 바인딩은 함수 호출 방식에 의해 동적으로 결정
    • 자바나 C++ 같은 클래스 기반 언어에서 this 는 언제나 클래스가 생성하는 인스턴스를 가리킨다.
    • 엄격 모드 역시 this 바인딩에 영향을 준다.
      • 일반 함수 내부의 this 에는 undefined 바인딩
  • this 는 코드 어디든 참조 가능하다.

함수 호출 방식과 this 바인딩

1. 일반 함수 호출

  • 일반 함수로 호출된 모든 함수는 전역 객체 바인딩 (window)
  • strict mode 면 undefined
  • 메서드 내에 정의한 중첩 함수도 일반 함수로 호출되면 중첩 함수 내부의 this 에는 전역 객체 바인딩
    • 콜백 함수도 마찬가지

2. 메서드 호출

  • 이름 앞의 마침표(.) 연산자 앞에 기술한 객체가 바인딩된다.
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

3. 생성자 함수 호출

  • (미래에) 생성할 인스턴스가 바인딩
// 생성자 함수
function Circle(radius) {
	// 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.
	this.radius = raduis;
	this.getDiameter = function () {
		return 2 * this.radius;
	};
}

// 반지름이 5인 Circle 객체를 생성
const circle1 = new Circle(5);
// 반지름이 10인 Circle 객체를 생성
const circle2 = new Circle(10);

console.log(circle1.getDiameter()); // 10
console.log(circle2.getDiameter()); // 20

// new 연산자와 호출하지 않으면 일반적인 함수 호출이다.
const circle3 = Circle(15);

console.log(circle3); // undefined 반환문이 없으므로
console.log(radius); // 15 전역 객체 가리킴

4. Function.prototype.apply/call/bind 메서드에 의한 간접 호출

  • apply , call , bind 메서드는 Function.prototype 의 메서드다.
  • 모든 함수가 상속받아 사용할 수 있다.
  • 두 메서드는 전달하는 방식만 다르고 this 로 사용할 객체를 전달하면서 호출하는 것은 동일하다.
  • bind 메서드는 호출하지 않고 바인딩만 해준다.
function getThisBinding() {
	console.log(arguments);
	return this;
}

// this 로 사용할 객체
const thisArg = { a: 1 };

// getThisBinding 함수를 호출하면서 인수로 전달할 객체를 getThisBinding 함수의 this 에 바인딩한다.
// apply 메서드는 호출할 함수의 인수를 배열로 묶어 전달
console.log(getThisBinding.apply(thisArg, [1,2,3]));
// Argument(3) [1,2,3, callee: f, Symbol(Symbol.iterator): f]
// {a: 1}

// call 메서드는 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달
console.log(getThisBinding.apply(thisArg, [1,2,3]));
// Argument(3) [1,2,3, callee: f, Symbol(Symbol.iterator): f]
// {a: 1}

console.log(getThisBinding.bind(thisArg)); // getThisBinding
console.log(getThisBinding.bind(thisArg)()); // {a: 1}

Categories:

Updated:

Leave a comment