[JS] This의 모든 가능성(모든 아님)

게코젤리·2023년 5월 19일

1. 전역에서의 this

function func() {}
console.log(this); // window

2. 함수 선언문, 함수 표현식으로 정의된 함수에서의 this

2-1. 전역에서 호출된 함수

function func() { 
    console.log(this);
}
const func2 = function(){
    console.log(this);
} 
func(); // window // strict 모드에선 undefined
func2();// window // strict 모드에선 undefined

2-2. 메소드로 호출

this는 해당 함수를 호출한 객체를 참조

function func() { 
    console.log(this);
}
const obj1 = {
  	name : 'kim',
  	func
}

const obj2 = {
  	name : 'hong',
	func : function(){
		console.log(this)
	},
  	func2(){
		console.log(this)
    }
}
obj1.func() // obj1
obj2.func() // obj2
obj2.func2() // obj2

2-3. 메소드를 다른 객체에 할당한 후 호출

호출된 객체를 참조.

const obj1 = {
	name: 'kim',
    func(){
		console.log(this);
	}
}
const obj2 = {
	name: 'hong'
}
obj2.func = obj1.func;
obj2.func() // obj2

2-4. 메소드를 분해할당으로 호출

본래의 객체와 별개의 독립적인 함수로 취급

const obj1 = {
	name: 'kim',
    func(){
		console.log(this);
	}
}
const { func } = obj1;
func() // window

3. 화살표 함수에서의 this

화살표 함수 내에서 this는 화살표 함수를 둘러싼 가장 가까운 일반 함수나 전역 스코프의 this를 바인딩.

3-1. 전역에서 호출

const func1 = () => { 
    console.log(this);
}

function func2()
	// func2의 this : Window
	const fun3 = () => console.log(this);
  	func3();
}

func1() // Window
func2() // Window

3-2. 메소드로 호출

function func() { 
    console.log(this);
}
const obj1 = {
  	name : 'kim',
  	func
}

const obj2 = {
  	name : 'hong',
	func : function(){
		console.log(this)
	},
  	func2(){
      	// func2의 this : obj2
		const func3 = () => console.log(this);
      	func3();
    }
}
obj1.func() // Window
obj2.func() // Window
obj2.func2() // obj2

4. 이벤트 핸들러 내부에서의 this

이벤트 핸들러 내부에서 this가 이벤트의 대상(target)이 되길 원한다면, 화살표 함수 대신에 일반 함수를 사용해야 한다.

document.querySelector('button').addEventListener('click', function() {
  console.log(this);  // 'this'는 클릭된 버튼 요소
});

document.querySelector('a').addEventListener('click', () => {
  console.log(this);  // Window
});

5. class, 생성자 함수에서의 this

this는 새로 생성된 객체를 참조.
화살표함수는 항상 인스턴스를 가리키지만 일반 함수의 경우 호출 위치에 따라 동적으로 결정

5-1. 생성자 함수

function MyConstructor() {
	this.greet = 'Hello, world!';
	this.func1 = () => {
		console.log(this)
    }
    this.func2 = function(){
        console.log(this);
    }
}
const myInstance = new MyConstructor();
myInstance.func1() // MyConstructor
myInstance.func2() // MyConstructor

const func3 = myInstance.func1();
const func4 = myInstance.func2();
func3(); // MyConstructor
func4(); // Window

5-2. Class

Class는 기본적으로 strict mode에서 실행된다. 그 부분에서 생성자 함수와의 차이가 있다.

class MyClass {
  constructor(name) {
    this.name = name;
  }
  func1 = () => {
    console.log(this);
  }
  func2() {
    console.log(this);
  }
  
}


const myInstance = new MyClass();
myInstance.func1() // MyClass
myInstance.func2() // MyClass

const func3 = myInstance.func1();
const func4 = myInstance.func2();
func3(); // MyClass
func4(); // undefined // Class는 기본적으로 strict mode

6. bind, call, apply 메서드로 바인딩한 함수

화살표 함수는 this를 변경하려고 해도 변화가 없다.

const obj1 = {
  	name: 'hong',
}

function func1(){
	console.log(this)
}

const bindFunc = func1.bind(obj1);
bindFunc(); // obj1
func1.call(obj1); // obj1
func1.apply(obj1); // obj1
// 화살표 함수

const func2 = () => {
	console.log(this)
}

const bindFunc2 = func1.bind(obj2);
bindFunc2(); // window
func2.call(obj2); // window
func2.apply(obj2); // window

7. 객체의 메서드를 콜백으로 사용할 때

객체의 메서드를 다른 함수의 콜백으로 전달할 때 'this'는 전역 객체를 가리킬 수 있다.

const myObj = {
  name: 'My Object',
  showThis: function() {
    console.log(this);
  }
};

setTimeout(myObj.showThis, 1000); // this는 Window
// setTimeout이 myObj.showThis 함수를 직접 호출. setTimeout이 함수를 호출하므로 this 값은 window 객체.
setTimeout(() => myObj.showThis(), 1000); // this는 myObj
// setTimeout이 화살표 함수를 호출하고, 그 화살표 함수가 myObj.showThis를 호출한다. this의 값은 함수가 호출되는 방식에 따라 결정되므로, 이 경우에는 myObj.showThis가 myObj를 this로 가진다.

0개의 댓글