this

Jun Hyoung Park·2022년 4월 19일
0

this 필요성

객체의 동작을 나타내는 메서드는 자신이 속한 객체의 프로퍼티를 참조하고 변경할 수 있어야 한다

  • 위와 같은 특성을 해결하기 위해 제공되는 자기 참조 변수
    • 자기 참조 변수 = 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 변수

함수 호출 방식과 this 바인딩

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

일반 함수 호출

  • this = window(전역 객체가 바인딩)
  • 일반 함수로 호출될 시 모든 this는 전역 객체가 바인딩된다
function foo(){
  console.log("foo's this: ", this); // window
  function bar(){
  	console.log("bar's this: ", this); //window
  }
  bar();
}
foo();
  • 문제점
    • 메서드 내에서 정의한 중첩 함수 또는 메서드에게 전달한 콜백 함수가 일반 함수로 호출될 때 this가 전역 객체를 바인딩되는 문제가 있다
      • 이런 문제는 헬퍼 함수로써의 역할을 수행하지 못하게 된다
//해결책
// this를 다른 변수에 할당하여 사용
// 다른 방법으로는 Function.prototype 메서드인 apply, call, bind를 이용하여 간접적으로 this의 바인딩을 설정하는 방법이 있다 이는 뒤에서 설명
var value = 1;

const obj ={
 	value: 100,
  	foo() {
      const that = this;
      
      setTimeout(function(){
        console.log(that.value); //100
      },100);
    }
 }
};
obj.foo();

메서드 호출

  • 메서드 내부의 this는 메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩된다
    • 이러한 특징을 보이는 이유는 객체에 정의된 메서드 프로퍼티는 사실 프로퍼티가 함수 객체를 가리키고 있을 뿐이기 때문이다
    • 프로토타입 메서드도 똑같이 바인딩된다
//이유 예제
const person ={
 	name: 'lee';
  // getname 프로퍼티 -> return this.name 역할을 하는 함수 객체를 가리키고 있다(바인딩)
  	getNmae() {
		return this.name;
    }
	
};
console.log(person.getName()); //lee

//작동 에제
const anotherPerson ={
  name:'Kim';
};

anotherPerson.getName = person.getName;
//메서드를 호출하는 객체 = anotherPerson
console.log(anotherPerson.getName()); //Kim

const getName = person.getName;
//일반 함수로 호출  = window 전역 객체
console.log(getName()); //''

생성자 함수 호출

  • 생성자 함수가 생성할 인스턴스가 바인딩된다
function Circle(radius){
	this.radius = radius;
  	this.getDiameter = function (){
      return 2 * this.radius;
    };
}

const circle1 = new Circle(5);
const circle2 = new Circle(10);

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

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

Function.prototype의 메서드이기 때문에 모든 함수가 상속받아 사용할 수 있다

apply, call 메서드

  • 첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩 하다
  • 둘의 차이점은 두 번째 인수로 전달하는 인수들을 나열하는 방식에 있다
function getThisBinding(){
	console.log(arguments);
    return this;
}

const thisArg = {a:1};
// 두 번째 인수 전달 방식이 다르다
console.log(getThisBinding.apply(thisArg, [1,2,3]));
// Arguments(3) [1,2,3]
// {a:1}
console.log(getThisBinding.call(thisArg, 1,2,3))
//Arguments(3) [1,2,3]
//{a:1}
  • 대표적인 용도(배열에서 다시 볼 예정이다)
    • Arguments 객체를 배열로 변환하여 사용할 경우
function convertArgsToArray(){
  console.log(arguments);
  // call == apply
  // Array.prototype.slice를 인수 없이 호출하면 배열의 복사본을 생성
  const arr = Array.prototype.slice.call(arguments);
 
  console.log(arr);
  
  return arr;
  
}
convertArgsToArray(1,2,3); // [1,2,3]

bind

  • apply,call 메서드와 달리 함수를 호출하지 않고 this로 사용할 객체만 전달
function getThisBinding(){
 	return this; 
}

const thisArg = {a:1};

console.log(getThisBinding.bind(thisArg)); //getThisBinding
console.log(getThisBinding.bind(thisArg)()); // {a:1} 명시적 호출
  • 용도
    • 위에서 이야기 했던 일반 함수의 호출의 문제점을 해결하는데 사용된다
      • 중첩 함수와 콜백 함수가 일반 함수로써 호출이 되면 this가 전역 객체에 바인딩되는 문제
const person={
	name: 'Lee',
    foo(callback){
      setTimeout(callback.bind(this), 100); 
    }
};

person.foo(function(){
  console.log(`Hi! my name is ${this.name}.`); // Hi! my name is Lee.
});
profile
프론트엔드 지망생

0개의 댓글