티스토리 뷰

Java에서의 this, Python에서의 self는 명확하게  현재 인스턴스 자신을 나타냅니다.

객체 내에서 this를 씀으로써 자신의 인스턴스 변수나 함수에 접근을 할수가 있습니다.

 

하지만 JavaScript에서의 this는 실행 컨텍스트에 따라 다르게 동작합니다.

함수가 어떻게 호출되었느냐에 따라 this의 값이 동적으로 결정됩니다.

또한 일반적인 함수에서 this는 호출한 객체를 나타내며, 화살표 함수에서는 함수가 생성될 때 상위 스코프의 this를 유지합니다.

 

this란??

함수가 호출되는 시점의 실행 컨텍스트(Execution Context)입니다. 

JavaScript의 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체 입니다.

즉, 함수를 실행하는 환경(호출하는 방법, 환경)이 달라지면 this도 변할 수 있는 것이 this입니다.

 

1. 전역 컨텍스트에서의 this 

전역 범위에서의 this는 전역 객체를 나타냅니다.

브라우저 에서는 window객체를 Node.js 환경에서는 global객체를 나타냅니다.

console.log(this); // window 또는 global

 

2. 함수 호출에서의 this

함수가 호출될 때 일반적으로 this는 호출한 객체를 나타냅니다.

function myFunction() {
	console.log(this);
  }
  
  myFunction(); // this는 전역 객체
  
  
  const obj = {
	myMethod: myFunction
  };
  
  obj.myMethod(); // this는 obj
  
  const func = obj.myMethod;
  func(); // this는 전역 객체
  
  const obj2 = {
  func1: function(){
    function hello(){
      console.log(this);
    }
    hello();
  }
  
  obj.func1(); // window 출력

Default Binding

  ● this바인딩 규칙 중 하나입니다. 다른 규칙이 적용되지 않을 때 사용됩니다.

  ● 함수를 단독으로 호출했을 때 적용되며, 이때 this는 전역 객체를 참조합니다.

  ● strict mode('use strict')에서는 전역 객체를 참조하지 않고 undefined가 됩니다.

 

myFunction()처럼 전역적으로 선언한 함수를 호출한 경우에는

Default Binding(기본 바인딩)으로 this는 전역객체에 할당되게 됩니다.

 

obj.myMethod()처럼 호출을 하게 되면 myMethod함수가 obj객체의 메서드로 호출되었기 때문에,

호출 위치의 객체(obj)가 this에 바인딩되고 this는 obj를 참조하게 됩니다.

 

하지만 func()처럼 호출을 하게 되면 전역 객체를 참조하게 됩니다.

obj.myMethod를 호출하면 obj를 참조하는것 아니냐? 할수 있습니다.

obj.myMethod를 func변수에 할당을 하면서 함수의 참조만을 복사했기 때문에

func를 통해 호출할 때에는 기본 바인딩이 적용되어서 this는 전역객체를 참조하게 됩니다.

함수의 참조만을 복사한 경우에는

해당 함수가 어떤 객체의 메서드로 호출되었는지 상관하지 않고, 호출 위치에 따라 this가 결정됩니다.

즉, 전역적으로 선언된 함수는 window객체(node는 global)가 가지고 있으므로 window객체가 호출하는 것과 같고

그렇기 때문에 this에 window객체가 바인딩 된다고 생각하면 될것 같습니다.

 

obj2.func1을 호출하면 func1이 obj 객체의 메소드로 호출되어 this는 obj를 참조합니다.

하지만 hello()함수는 일반적인 함수로 호출되어 자체적인 this가 없습니다.

따라서 이 부분은 전역 컨텍스트에서의 this를 참조하므로 window객체를 참조하게 됩니다.

이부분은 설계 단계의 결함이므로 이를 해결하려면 화살표 함수를 쓰거나

bind등으로 명시적으로 지정해 줄수 있습니다.

 

3. 메소드에서의 this

객체의 메소드 내에서 this는 해당 메소드를 호출한 객체를 가리킵니다.

function Func1() {
	console.log(this);
}

const myObject = {
	myMethod: function () {
		console.log(this);
	},
	Func : Func1
};

const myObject2 = {
	name: 'coriny',
}
myObject2.myMethod = myObject.myMethod;
myObject.myMethod(); // this는 myObject
myObject2.myMethod(); // this는 myObject2
myObject.Func(); // this는 myObject

객체의 메소드를 호출할 경우에는 암시적 바인딩이 적용되어, 해당 메소드를 호출한 객체에 바인딩 됩니다.

다른 객체와 전역적으로 선언된 함수여도 호출한 객체에 따라 this가 바인딩 되는것을 알수가 있습니다.

 

 

4. 생성자에서의 this

생성자 함수 내에서 this는 생성된 인스턴스를 가리킵니다.

function MyClass() {
  this.myProperty = 42;
}

const myInstance = new MyClass();
console.log(myInstance.myProperty); // 42

console.log('----------------------------')

function Car(color, speed) {
  this.color = color;
  this.speed = speed;
}

// 새로운 객체 생성
const redCar = new Car('red', 60);
console.log(redCar.color); // 'red'
console.log(redCar.speed); // 60

생성자 함수는 new키워드와 함께 호출될 때마다 새로운 객체가 생성되고,

이때 this는 새로 생성된 객체를 참조 합니다.

Car는 생성자함수이고 this.color, this.speed는 생성되는 새로운 객체의 속성으로 설정됩니다.

new Car를 사용하여 호출하면 새로운 Car객체가 생성되고 여기서 this는 새롭운 Car객체를 가리키게 됩니다. 

 

5. 화살표 함수에서의 this

화살표 함수에서의 this동작은 일반 함수와는 조금 다르게 작동합니다.

화살표 함수에서는 함수가 생성될 때 상위 스코프의 this를 유지하게 됩니다.

function MyClass(value) {
    this.value = value;
}

MyClass.prototype.printValue = function () {
    // 일반 함수 내에서의 this
    console.log(this.value);
};

MyClass.prototype.printValueArrow = () => {
    // 화살표 함수 내에서의 this
    console.log(this.value);
};

const obj = new MyClass(42);

obj.printValue();           // this는 obj
obj.printValueArrow();      // this는 상위 스코프의 this (전역 객체 또는 undefined)

pringValueArrow함수내에서 사용된 화살표 함수는 상위 스코프의 this를 참조합니다.

그렇기 때문에 obj의 속성인 value에 접근을 할 수가 없습니다.

화살표 함수의 경우 Lexical Scoping을 사용하기 때문에 함수가 선언된 위치에서의 스코프를 기반으로 this를 결정합니다.

 

6. call 과 apply

call과 apply메소드는 this를 특정 객체에 바인딩 해주면서 함수를 호출합니다.

function greet(name) {
	console.log(`Hello, ${name}! My name is ${this.name}.`);
}

const person = { name: 'John' };

greet.call(person, 'Alice'); // Hello, Alice My name is John.
greet.apply(person, 'Alice') // Hello, Alice My name is John.

call 메소드함수를 호출하면서 특정 객체를 함수 내부의 this로 지정합니다.

함수를 호출하면서 여러개의 인자를 전달할수 있으며 call 메소드를 사용하여 greet함수를 호출할 때,

person 객체가 this로 지정되었습니다.

apply메소드도 마찬가지이지만 인자들만 배열형태로 전달되었습니다.

일반적으로 call과 apply는 함수의 this를 특정 객체로 지정하거나, 함수에 인자를 동적으로 전달할 때 사용됩니다.

화살표 함수가 도입되면서 필요한 경우가 상당히 줄었지만 여전히 사용되고 있습니다.

 

7. bind

bind는 이름에서 알 수 있듯이 this에 바인딩하는 역할을 위해 만들어졌습니다.

함수를 호출하면서 새로운 함수를 생성하여 특정 객체를 함수 내에서 사용되는 this에 영구적으로 바인딩할 때 사용됩니다. 

/* bind 메소드 사용 */
function greet(name) {
	console.log(`Hello, ${name}! My name is ${this.myName}.`);
}
const person = { myName: 'John' };

// bind 메소드를 사용하여 새로운 함수 생성
const boundGreet = greet.bind(person);

// 새로운 함수 호출
boundGreet('Alice');// Hello, Alice My name is John.

console.log('------------------------------------')

/* 콜백함수 등록 사용 */
function greet(name) {
	console.log(`Hello, ${name}! My name is ${this.myName}.`);
}
const person = { myName: 'John' };
setTimeout(greet.bind(person,'Alice'),1000); // 1초 뒤에 Hello, Alice! My name is John. 출력

console.log('------------------------------------')

/* 일부인자 미리고정 */
function add(a, b) {
  return a + b;
}

// 두 번째 인자를 5로 고정한 새로운 함수 생성
const add5 = add.bind(null, 5);

// 새로운 함수 호출
console.log(add5(3)); // 8

bind메소드를 사용하여 greet함수에서 사용될 this를 person객체로 지정한 새로운 함수 boundGreet을 생성합니다.

이후에 boundGreet을 호출하면 this는 항상 person객체로 고정되게 됩니다.

함수를 호출하는 것이 아닌 반환해주는 것이기 때문에, 콜백 함수를 등록할 때도 사용할 수 있습니다.

또한 bind메소드는 함수의 this를 고정하는데 활용되기도 하면서 특정함수에서 일부 인자를 미리 고정하는 데도 사용됩니다.

add5함수는 add함수에서 첫번째 인자 a가 항상 5로 고정된 새로운 함수가 되었습니다.

이렇게 하면 첫번째 값은 항상 5가 들어가고 그 이후 값으로 3이 들어가게 됩니다.

 

 

자바스크립트의 this에 대해서 이해하기가 힘들어 다시한번 정리해 봤습니다.

 

 

 

 

배워나가는 코린이 입니다!!

부족한게 있다면 댓글로 지적해주세요!! 감사합니다!😊

'프로그래밍 기초 > JavaScript' 카테고리의 다른 글

TIL 8일차 + 실행 컨텍스트란?  (1) 2024.01.03
TIL 7일차 + 배열이란?  (2) 2024.01.02
구조 분해 할당이란?  (1) 2024.01.02
화살표 함수란?  (0) 2024.01.02
TIL 6일차 + JavaScript 기초  (2) 2023.12.29
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함