Deep Dive - 22.this

Jihyun-Jeon·2022년 3월 7일
0

Javascript - Deep Dive

목록 보기
6/26

🔶 this가 필요한 이유

:함수 자신이 속한 객체나 자신이 생성할 인스턴스를 가리킬 수 있기 위해서.

🔶 this 바인딩 이란

:this와 this가 가리킬 객체를 연결하는 것

🔶 this는 함수를 "호출하는 방식"에 따라 달라진다.

  • this에 바인딩될 객체는 호출 시점에 결정됨.

1. 콜백함수, 중첩함수 등 어떠한 함수라도 일반 함수로 호출되면, 그 함수 내부의 this는 "전역객체, window" 가 바인딩 된다.

  • 일반함수호출
    function foo(){
     console.log(this); // window
      function bar(){
        console.log(this); // window
       }
       bar();
     }
    foo();
    ``
    	
  • 메서드 내에서 정의한 중첩함수도 일반함수로 호출되면 중첩함수 내부의 this는 window임.
const obj = {
	value: 100;

	foo(){
	console.log(this); // [p1] obj객체 {value:100, foo : fn()}
	function bar(){
		console.log(this) // [p2] window
	   }
	bar(); // [p2]일반함수 호출
    }

}

obj.foo();	// [p1]메서드 호출
  • 콜백함수도 일반 함수로 호출되면 콜백함수 내부의 this도 window가 바인딩 됨.
	const person = {
    	name : "Lee"
      
      	foo(){
          //foo함수 안의 콜백함수는 일반함수 호출임. 따라서 this는 window임.
       	 	setTimeout(function(){ 
        		console.log(this.name);  
        		}, 100)
       		 }

    	};

person.foo();

2.메서드 호출

  • 메서드 내부의 this는 , 메서드를 호출한 객체(쉽게말하면 점.앞에 있는 객체)가 this가 된다.

  • 예제

const obj = {
	name : "Lee";
  	foo(){
    	 return this.name; // "Lee"
    }
  }
  
  obj.foo(): // 메서드 foo를 호출한 객체인 obj가 this가 됨.

3.생성자 함수로 호출

  • 생성자 함수 내부의 this는 생성자 함수가 생성할 인스턴스 객체에 바인딩 됨.
  • 예제
 function Circle(num){
   this.radius : num;
   this.diameter = function(){
   		return this.radius * 2;
   }
 }

new Circle(5); // {radius : 5, diameter : fn}
new Circle(10); // {radius : 10, diameter : fn}

4. apply, call, bind

1) 형태: apply(thisArg,[1,2,3]) , call(thisArg, 1,2,3) , bind(thisArg, 1,2,3)
: apply(this로 사용할 객체, 함수에게 전달할 인자를 배열 형식으로 전달) : 함수를 호출함
: call (this로 사용할 객체, 함수에게 전달할 인자를 쉼표로 구분하여 전달) : 함수를 호출함
: bind (this로 사용할 객체, 함수에게 전달할 인자를 쉼표로 구분하여 전달) : 함수를 호출하지 않음.(명시적으로 호출해 줘야함.)

2) apply,call 과 bind 차이

  • apply,call
    : 함수를 실행할 때, (함수의 컨텍스트) this 값을 바꾸어 함수를 호출함.
  • bind
    : 어떤 함수의 this값을 영구적으로 바꾼 새로운 함수를 만들어 반환함.
    : (함수가 호출되는건 아님)

3) 예제

  • apply,call 예제
 function test(){
   console.log(arguments)
  return this;
 }

const obj = {a:1}; //this로 지정할 객체

test(); // window
test.apply(obj, [1,2,3]); // arguments(3) [1,2,3] // {a:1}
test.call(obj, 1,2,3); // arguments(3) [1,2,3] // {a:1}
  • bind 예제1
function test(){
 return this;  
}

const obj = {a:1};

test.bind(obj);   // bind메서드는 this를 지정만 하고, 함수를 호출하지 않음 
test.bind(obj)(); // 따라서 명시적으로 호출해야 한다 
  • bind 예제2
    :콜백함수가 일반함수로 호출되기 때문에, bind(this)로 this를 person으로 지정해줌.
    :bind(this)는 메서드를 호출한 객체를 가르키게 됨.
const person = {
 name : "Lee",
  foo(){
  	setTimeout(function(){
    	console.log(`hello,${this.name}`);
    }.bind(this),1000)
  }
}

person.foo(); //hello,Lee

🔶 arrow함수 내에서의 this

arrow함수 내에서의 this는 한단계 위의 스코프를 가르킴

import { makeAutoObservable } from "mobx";

const Store = () => {
  return makeAutoObservable({
    list: ["잠자기", "쉬기"],
    // < 올바른 코드 >
    // add함수에서의 this는 :  makeAutoObservable()안에 있는 객체를 가르킨다.
    add(content) {
      this.list.push(content);
    },

    // < 잘못된 코드 >
    // 1. arrow 함수는 상위 스코프의 this를 가리킴
    // 따라서 한단계 위의 스코프가 this가 되는것임!
    //
    // 2.이런식으로 arrow 함수로 쓰면 this가 undefined가 됨
    // module 컨텍스트의 최상위 this는 undefined임
    delete: (idx) => {
      console.log(this);
      this.list.split(idx, 1);
    },
  });
};

0개의 댓글