하루하루 꾸준히, 인생은 되는대로

자바스크립트

자바스크립트 this

긤효중 2023. 1. 30. 14:16

this는 함수를 호출한 방식에 따라 다르게 정의된다.


객체 리터럴의 메서드의 this

const circle = {
	radius:5,
    getRadius(){
    	return this.radius;
   }
 };
 
 console.log(circle.getRadius());

객체 리터럴의 메서드 내부에서 this는 메서드를 호출한 객체와 바인딩된다.

다음의 경우를 살펴보자

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

const anotherperson = {
    name:'Kim'
};

anotherperson.getName = person.getName;

console.log(anotherperson.getName());

const getName = person.getName;

console.log(getName());

먼저 person객체의 메서드로 getName을 정의했다.

그 후 getName메서드를 anotherPerson 객체의 메서드로 할당하고,

getName메서드를 변수 getName에 할당해서 호출을 하였다.

 

콘솔에는 다음과 같이 출력된다.

메서드를 호출한 객체가 anotherperson -> 전역객체(window)이기 떄문에,

anotherperson의 name,window의 name이 출력되는 것을 볼 수 있다.

 

메서드를 호출한 객체에 this가 바인딩된다.


생성자 함수 내부의 this

function Circle(radius){
    this.radius = radius;
}

Circle.prototype.getRadius = function(){
    return this.radius;
};

const circle = new Circle(5);
console.log(circle.getRadius()); // 5

생성자 함수 내부에서 this는 생성자 함수가 생성할 인스턴스를 가르킨다.


일반 함수로서 호출시 this

const foo = function(){
    return this;
}

console.log(foo()); //window

일반 함수로 호출시 this는 전역 객체와 바인딩된다.

중첩 함수도 일반 함수로 호출하면 마찬가지로 this는 전역 객체와 바인딩된다.

const foo = function(){
    console.log(this);
       const bar = function(){
        console.log(this);
    }
    bar();
}

foo(); //window window

생성자 함수 호출시

function Circle(radius){
    this.radius = radius;
    this.getRadius = function(){
        return this.radius;
    };
}

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

console.log(circle1.getRadius()); //5
console.log(circle2.getRadius()); //10

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


화살표 함수에서의 this

일반함수는 함수를 호출 방식에 따라 this가 동적으로 결정되었다.

하지만 ES6에서, 이 규칙을 따르지 않는 특별한 함수인 화살표 함수가 추가된다.

화살표 함수는 함수 선언 시, this에 바인딩 할 객체가 정적으로 결정된다.

 

일반 함수와 달리 this에 바인딩 될 객체는 언제나 상위 스코프의 this이다.

const introObject = {
    name: "Kim",
    nickname: "HJ",
    getIntro: function() {
      innerFunc = () => `${this.name}님의 닉네임은 ${this.nickname}입니다.`;
      console.log(innerFunc());
    }
  };
  introObject.getIntro(); //Kim님의 닉네임은 HJ입니다.

위의 경우 innerFunc의 상위 스코프 introObject가 this와 바인딩되는 것을 볼 수 있다.


Function.prototype.apply,call,bind에 의한 호출

위의 메서드는 this로 사용할 객체, 인수 리스트를 전달받아 함수를 호출한다.

function getThisBinding(){
    return this;
}

//this로 사용할 객체
const thisArg = {a:1};
console.log(getThisBinding()); //window

//getThisBinding함수를 호출하면서 
//인수로 전달한 객체를 this와 바인딩한다

console.log(getThisBinding.call(thisArg)); //{a:1}
console.log(getThisBinding.apply(thisArg));//{a:1}

apply,call메서드는 함수 호출 시 첫번쨰 인수로 전달한 객체를,

호출한 함수의 this와 바인딩한다.

 

apply,call의 대표적 용도는 arguments객체와 같은 유사 배열 객체에서,

배열 메서드를 쓰고 싶을 떄이다.

 

function convertArgstoArray(){
    console.log(arguments);

    //arguments객체를 배열로 변환
    const arr = Array.prototype.slice.call(arguments);
    console.log(arr);
    return arr;
}
convertArgstoArray(1,2,3); //[1,2,3]

ES6부터 Array.from()이라는 메서드를 쓸 수 있다.

유사배열객체를 얕게 복사해 새 Array 객체로 만든다!