JS Study 4주차 ( this )

jaehan·2023년 5월 6일
0

JavaScript

목록 보기
25/33
post-thumbnail

this

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

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

ex)

console.log(this); // window

function square(number){
  console.log(this); // window
  return number * number;
}
square(2);

const person = {
  name: 'kim',
  getName() {
    console.log(this); // {name: "kim", getName: f}
  }
};
console.log(person.getName());

function Person(name) {
  this.name = name;
  console.log(this); // Person {name: "kim"}
}

const me = new Person('kim');
  • 전역에서 this는 전역객체 window를 가리킨다.
  • 일반 함수 내부에서 this는 전역객체 window를 가리킨다.
    📌 strict mode에서는 일반함수 내부의 this에서는 undefined 바인딩된다
  • 메서드 내부에서 this는 메서드를 호출한 객체를 가리킨다.
  • 생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가리킨다.

함수 호출방식에 따른 this 바인딩

일반함수 호출

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

메서드 내의 중첩 함수도 일반 함수로 호출되면 그 내부의 this에도 전역객체가 바인딩 된다.

var value = 1;

const obj = {
  value: 100,
  foo(){
    console.log(this) // {value: 100, foo:f}
    
    function bar(){
      console.log(this) // window
    }
    bar();
  }
}

obj.foo();
  • foo()는 메서드 내부의 this이기 때문에 obj를 가리킴
  • bar()는 일반 함수로 호출되었기 때문에 window 즉 전역객체를 가리킴

하나의 예시를 더보면 위의 예시에서 bar자리에 setTimeout이 있다고 생각하는 것이다

setTimeout(function (){
  console.log(this) // window
}, 100)

// 해결 방법
const that = this;
setTimeout(function (){
  console.log(that)
}, 100)

setTimeout(function (){
  console.log(this) 
}.bind(this), 100)

setTimeout(()=>console.log(this), 100);
  • setTimeout도 일반함수이기 때문에 this는 전역객체를 가리킴
  • 상위에서 this를 변수 선언해서 사용한다.
  • Function.prototype.bind를 사용한다.
  • 화살표 함수를 사용한다 (화살표 함수 내부의 this는 상위 스코프의 this를 가리킴)

메서드 호출

메서드 내부의 this에는 호출한 객체 즉 메서드 이름앞의 마침표 연산자 앞에 기술한 객체가 바인딩 된다.

const person = {
  name: 'kim',
  getName(){
    return this.name;
  }
}

const anotherPerson = {
  name: 'lee'
}

anotherPerson.getName = person.name;

const getName = person.getName;

console.log(person.getName()) // kim
console.log(anotherPerson.getName()) // lee
console.log(getName()) // ''

위의 예시처럼 getName은 function object라는 함수 객체를 가리키고 있고 이 객체안에 this가 들어있다.
따라서 this는 마침표 연산자로 메서드를 호출하면 마침표 연산자 앞에 기술한 객체와 바인딩 되어 해당 객체를 가리키게 되는 것이다.
📌 프로토타입도 마찬가지이다.

생성자 함수 호출

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

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

위와 같이 new 와 함께 사용하면 생성자 함수로써 호출되는데 그렇게 되면 내부의 this는 생성된 인스턴스를 가리키게 된다.

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

apply, call, bind 메서드는 Function.prototype의 메서드다. 따라서 모든 함수는 이 메서드를 상속받아 사용할 수 있다.


function getThisBinding(){
  return this;
}

const thisArg = {a : 1};

console.log(getThisBinding()) // window

console.log(getThisBinding.apply(thisArg)) // {a:1}
// getThisBinding.apply(thisArg, [1, 2, 3])
console.log(getThisBinding.call(thisArg)) // {a:1}
// getThisBinding.call(thisArg, 1, 2, 3)
console.log(getThisBinding.bind(thisArg)); //getThisBinding
console.log(getThisBinding.bind(thisArg)()); // {a:1}

apply, call 메서드의 본질적인 기능은 함수를 호출하는 것이다.
apply, call 메서드는 함수를 호출하면서 첫번째 인수로 전달한 특종 객체를 호출한 함수의 this에 바인딩 한다.

📌 인수를 같이 전달할 수도있다

bind는 첫번째 인수로 전달한 값으로 this바인딩이 교체된 함수를 새롭게 생성해 반환한다.

마무리

  • 일반 함수 호출: 전역객체
  • 메서드 호출: 메서드를 호출한 객체
  • 생성자 함수 호출: 생성자 함수가 생성할 인스턴스
  • apply, call, bind: 첫번째 인수로 전달한 객체

참고 :
https://www.inflearn.com/course/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%94%A5%EB%8B%A4%EC%9D%B4%EB%B8%8C

0개의 댓글