[JS] this와 바인딩

POLO·2024년 1월 19일

this와 바인딩

this

일반적으로 this는 자신이 속한 인스턴스를 가리키는 자기참조 변수(Self-Reference Variable)이다.
자바스크립트에서의 this에 대해 알아보기 전에 먼저 전역 객체에 대해 알아보자!

전역 객체

자바스크립트로 동작하는 브라우저 환경에서의 전역 객체는 window이다.

사용 환경에 따라 전역 객체가 다르다.
Node.js환경에서 동작하는 전역 객체는 global이다.

전역 객체는 말 그대로 전역 범위에 존재하기 때문에 어떤 범위에서든 호출할 수 있다.

탭 기능이 있는 브라우저에서는 각각의 탭이 항상 자신의 탭을 가리키는 window 객체를 가지게 된다.
window 객체의 프로퍼티와 메서드가 궁금하다면 아래 MDN 문서를 참고하기 바란다.

window 인스턴스 속성
window 인스턴스 메서드


자바스크립트 this

일반적으로 this는 자신이 속한 인스턴스를 가리킨다고 했는데,
자바스크립트에서 this는 this가 포함된 함수를 호출한 객체를 가리킨다.

전역에서 사용된 this

console.log(this === window); // true

위와 같이 전역 범위에서 this가 어떤 객체를 가리키는지 확인해 보면 window를 가리키는 걸 볼 수 있다.

함수에서 사용된 this

function Hello() {
	console.log(this, "Hello"); 
}

Hello(); //window{}, Hello

위와 같이 전역 범위가 아닌 함수 범위에서 사용했음에도 불구하고 this가 window 객체를 가리키는 것을 볼 수 있는데, 이는 호출한 곳이 전역 범위이기 때문이다.

메서드에서 사용된 this

class Person {
	constructor(name) {
		this.name = name;
	}
	walk() {
		console.log(this.name + "이 걷습니다.");
	}
}

const kim = new Person("kim");
kim.walk(); //kim이 걷습니다.

walk 메서드는 kim 인스턴스에 의해 호출되기 때문에 walk 메서드 내에 있는 this.name은 자신을 호출한 kim 인스턴스에 있는 name을 가리키게 된다.

내부함수에서 사용된 this

const kim = {
    name: "kim",
    walk: function () {
        function drink() {
            console.log(this); // window 객체
            console.log(this.name + "은 마시면서 걷는다."); // undefined은 마시면서 걷는다.
        }
        console.log(this); // kim 객체
        console.log(this.name + "이 걷는다."); // kim이 걷는다.
        drink();
    }
}

kim.walk();

walk 메서드 안에 있는 내부 함수인 drink에서 this를 사용해봤다.
this가 kim객체가 될 거라 예상했지만 예상과는 다르게 window 객체가 참조되었다.

이는 자바스크립트에서 내부 함수 호출해 대해서 정의하지 않았기 때문인데
화살표 함수를 사용하면 예상과 같게 this가 kim 객체를 가르키게 된다.

const kim = {
    name: "kim",
    walk: function () {
        const drink = () => {
            console.log(this); // kim 객체
            console.log(this.name + "은 마시면서 걷는다."); // kim은 마시면서 걷는다.
        }
        console.log(this); // kim 객체
        console.log(this.name + "이 걷는다."); // kim이 걷는다.
        drink();
    }
}

kim.walk();

바인딩

바인딩에는 암시적 바인딩, 명시적 바인딩이 있다.

암시적 바인딩

암시적 바인딩은 위에서 작성한 코드와 같이 별도 바인딩이 없었기 때문에 this가 참조하는 객체가 함수가 호출되는 위치에 의해 정해지는 것이다.

명시적 바인딩

명시적 바인딩은 함수에서 this로 참조되는 객체를 함수로 전달해 해당 객체에 this를 바인딩하는 것이다.
명시적 바인딩은 bind(), call(), apply() 메서드를 이용해 구현할 수 있다.

bind 메서드

bind는 참조할 객체를 전달하면 해당 객체를 참조하는 새로운 함수를 반환한다.

const kim = {
    name: "kim",
    walk: function () {
        function drink()  {
            console.log(this); // kim 객체
            console.log(this.name + "은 마시면서 걷는다."); // kim은 마시면서 걷는다.
        }
        console.log(this); // kim 객체
        console.log(this.name + "이 걷는다."); // kim이 걷는다.
        drink.bind(kim)();
    }
}

kim.walk();

내부함수에서 사용된 this 예제 코드에 bind 메서드를 사용해 주면 화살표 함수가 아니더라도 kim 객체를 참조하게 할 수 있다.

apply()

apply는 인자로 this에 바인딩할 객체와 배열을 받아 함수를 바로 호출한다.
인자로 전달된 배열은 유사 배열 객체인 arguments를 통해 Key(Index)에 접근해 사용할 수 있다.

유사 배열 객체는 배열이 아닌 숫자(0,1,2,...)를 Key로 가지는 객체로 배열과 동일하게 length 속성을 가지고 있으나 배열 메서드 사용은 불가능하다.

const kim = {
    name: "kim",
    walk: function () {
        function drink()  {
            console.log(this); // kim 객체
            console.log(this.name + `은 ${arguments[0]}과 ${arguments[1]}을 마시면서 걷는다.`); // kim은 Cock과 Sprite을 마시면서 걷는다.
        }
        console.log(this); // kim 객체
        console.log(this.name + "이 걷는다."); // kim이 걷는다.
        drink.apply(kim, ['Cock', "Sprite"]);
    }
}

kim.walk();

call()

call은 인자로 this에 바인딩할 객체와 함께 여러 인자를 받아 함수를 바로 호출한다.

const kim = {
    name: "kim",
    walk: function () {
        function drink(drink1, drink2)  {
            console.log(this); // kim 객체
            console.log(this.name + `은 ${drink1}과 ${drink2}을 마시면서 걷는다.`); // kim은 Cock과 Sprite을 마시면서 걷는다.
        }
        console.log(this); // kim 객체
        console.log(this.name + "이 걷는다."); // kim이 걷는다.
        drink.call(kim, 'Cock', "Sprite");
    }
}

kim.walk();

0개의 댓글