본문 바로가기
개발 공부/웹개발

[javascript] this

by 크롱이크 2021. 11. 22.

✅  개념 

- this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수다.

- this를 통해 자신이 속한 객체 또는 자신이 생성할 인 스턴스의 프로퍼티나 메서드를 참조할 수 있다.

(자바스크립트 엔진에 의해 암묵적으로 생성, 코드 어디서든 참조 가능)

- this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.

✅  간단한 예제

//1번 예제

const circle = {
	// 프로퍼티: 객체 고유의 상태 데이터
	radius:: 5,
	getDiameter() {
		return 2 * circle.radius
  }
}

console.log(circle.getDiameter()); //10

// 2번 예제

const circle = {
	// 프로퍼티: 객체 고유의 상태 데이터
	radius:: 5,
	getDiameter() {
		return 2 * ????.radius
  }
}

this를 사용한 예제
const circle = {
	// 프로퍼티: 객체 고유의 상태 데이터
	radius:: 5,
	getDiameter() {
		return 2 * this.radius
  }
}

console.log(circle.getDiameter()); // 10

// this를 사용한 생성자 함수 예제
function Circle(radius){
	this.radius = radius;
}

Circle.prototype.getDiamneter = function () {
	return 2 * this.radius;
}

const circle = new Circle(5);
console.log(circle.getDiameter()); // 10

✅  this 바인딩은 함수 호출 방식, 함수가 어떻게 호출되었는지에 따라 동적으로 결정된다.

- 함수를 호출하는 방식은 다양하다

1. 일반 함수 호출

- 기본적으로 this에는 전역 객체 window가 바인딩 된다.

// 일반함수 호출 this 예제
function foo() {
  console.log(this) // window

	function bar() {
		console.log(this) // window
	}
	bar()
}

foo();

// use strict모드의 일반함수 호출 this

function foo() {
'use strict';
  console.log(this) // undefined

	function bar() {
		console.log(this) // undefined
	}
	bar()
}

foo();

2. 메소드 호출

- 메서드 내부의 this에는 메서드를 호출한 객체,

- 즉 메서드를 호출할 때 메서드 이름 앞의 마침표 연사자 앞에 기술한 객체가 바인딩 된다.

//1번 예제
const person = {
	name: 'Lee',
	getName(){
		return this.name
	}
}

//person이 바인딩 된다.
console.log(anotherPerson.getName()); // Lee

//2번 예제
const anotherPerson = {
	name: 'Kim'
}
//anotherPerson이 바인딩된다.
anotherPerson.getName = person.getName;

console.log(anotherPerson.getName()); //kim

//3번 예제
const getName = person.getName();

// 일반 함수로 호출되었기 때문에 getName의 함수 내부의 this.name은 window.name이 된다.
// 현재 window.name은 없기에 기본값인 ''
// Node.js에서는 undefined 
console.log(getName()); // ''

3. 생성자 함수 호출

- 생성자 함수 내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩 된다.

function Circle(radius){
	this.radius = radius;
	this.getDiameter = function(){
		return 2 * this.raduis;
	}
}

// 반지름이 5인 Circle 객체
const circle5 = new Circle(5);
// 반지름이 10인 Circle 객체
const circle10 = new Circle(10);

console.log(circle5.getDiameter()) // 10
console.log(circle10.getDiameter()) // 20

// but..
// new 연사자와 함께 생성자 함수를 호출하지 않으면 생성자 함수가 아니라 일반함수로 동작한다.

const circle3 = Circle(3);
console.log(circle3) // undefined

// 일반 함수로 호출된 Circle 내부의 this는 전역 객체를 가리킨다.
console.log(radius) //3

3. call, apply, bind

- 함수 호출 방식과 관계없이 this를 지정할 수 있음

- call 메소드는 모든 함수에서 사용할 수 있으며, this를 특정 값으로 지정할 수 있습니다.

const mike = {
  name: 'mike'
}

function showThisName() {
	console.log(this.name)
}

showThisName() // "" window.name은 빈값
showThisName.call(mike); // mike 나옴

function update(birthYear, occupation){
	this.birthYear = birthYear;
	this.occupation = occupation;
}

update.call(mike, 1999, "signer")
console.log(mike); // {birthYear: 1999, name: "mike", occupation: "signer"}

 

- apply는 함수 매개변수를 처리하는 방법을 제외하면 call과 완전히 같습니다.

- call은 일반적인 함수와 마찬가지로 매개변수를 직접 받지만, apply는 매개변수를 배열로 받는다.

// 1번 예시
const mike = {
	name: 'mike'
}

function update(birthYear, occupation){
	this.birthYear = birthYear;
	this.occupation = occupation;
}

update.apply(mike, [1999, "signer"])
console.log(mike); // {birthYear: 1999, name: "mike", occupation: "signer"}

// 2번 예시
const nums = [3,10,1,6,4];

const minNum = Math.min.apply(null, nums);
// 이거와 같은 것들은
// const minNum = Math.min.call(3,10,1,6,4);
// const minNum = Math.min.call(...nums);
const maxNum = Math.max.apply(null, nums);

console.log(minNum);
console.log(maxNum);

- bind() 메소드가 호출되면 새로운 함수를 생성한다.

- 받게 되는 첫 인자의 value로는 this 키워드를 설정하고, 이어지는 인자들은 바인드 된 함수의 인수에 제공된다.

 

// 1번 예시
const module = {
  x: 42,
  getX: function() {
  //this가 여기 있다
    return this.x;
  }
};

const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// undefined

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX()); // 42


// 2번 예시
function list() {
  return Array.prototype.slice.call(arguments);
}

const list1 = list(1, 2, 3); // [1, 2, 3]

// 선행될 인수를 설정하여 함수를 생성
const leadingThirtysevenList = list.bind(null, 37);

const list2 = leadingThirtysevenList();  // [37]

const list3 = leadingThirtysevenList(1, 2, 3);  // [37, 1, 2, 3]

 

✅  정리

- this는 자기 참조 변수이며, this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.(호출할 때마다 다르다)

- 크게 4가지로 보게 되면, 일반 함수, 메서드 호출, 생성자 함수, call, apply, bind를 호출할 때마다 다르게 바인딩한다.

 

 

출처:

모던 자바스크립트 Deep Dive 22장

https://www.youtube.com/watch?v=KfuyXQLFNW4 

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this

반응형

댓글