Javascript/Node.js

메서드와 this

Frankie 2021. 9. 27. 10:47

자바스크립트의 this는 다른 프로그래밍 언어의 this와 동작 방식이 다르다. 자바스크립트에선 모든 함수에 this를 사용할 수 있다.

function sayHi(){
	alert(this.name);
}

this 값은 런타임에 결정된다.(컨텍스트에 따라 달라진다.)

동일한 함수라도 다른 객체에서 호출했다면 this가 참조하는 값이 달라진다.

let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi(){
	alert(this.name);
}

//다른 두 객체에서 동일한 함수 사용
user.f = sayHi; 
admin.f = sayHi;

//this는 점(.) 앞의 객체를 참조하기 때문에 this 값이 달라진다.
user.f(); // John (this == user)
admin.f(); // Admin (this == admin)

admin['f'](); // Admin (점과 대괄호는 동일하게 동작)

객체 없이 호출하기: this == undefined

객체가 없어도 함수를 호출할 수 있다.

function sayHi(){
	alert(this):
}

sayHi(); // undefined

함수 본문에 this가 사용되었다면, 객체 컨텍스트 내에서 함수를 호출할 것이라고 예상하면 된다.

 

다른 언어를 쓰다가 자바스크립트로 넘어온 개발자는 this를 항상 메서드가 정의된 객체를 참조할 것이라고 착각하기 쉬운데 이런 개념을 'bound this'라고 한다.

 

자바스크립트에서 this는 런타임에 결정된다. 메서드가 어디서 정의되었는지 상관없이 this는 '점 앞의' 객체가 무엇인가에 따라 '자유롭게' 결정된다.

 

this가 없는 화살표 함수

화살표 함수는 일반 함수와 달리 고유한 this를 가지지 않는다. 화살표 함수에서 this를 참조하면, 화살표 함수가 아닌 '평범한' 외부 함수에서 this 값을 가져온다.

let user = {
	firstName: "보라",
    sayHi(){
    	let arrow = () => alert(this.firstName);
        arrow():
    }
 };
 
 user.sayHi(); // 보라

함수 arrow()의 this는 외부 함수 user.sayHi()의 this가 된다.

 

예) 객체 리터럴에서 'this' 사용하기

function makeUser() {
	return {
    	name: "John",
        ref: this
    };
};

let user = makeUser();
alert(user.ref.name); //Error: Cannot read property 'name' of undefined

에러가 발생하는 이유는 this 값을 설정할 땐 객체 정의가 사용되지 않기 때문이다. this 값은 호출 시점에 결정되기 때문에 makeUser() 내 this는 undefined가 된다. 메서드로써 호출된 게 아니라 함수로써 호출되었기 때문이다.

this 값은 전체 함수가 되고 코드 블록과 객체 리터럴은 여기에 영향을 주지 않는다.

따라서 ref: this는 함수의 현재 this 값을 가져온다.

 

에러가 발생하지 않게 하려면 다음과 같이 수정하면 된다.

function makeUser(){
	return{
    	name: "John",
        ref() {
        	return this;
        }
    };
};

let user = makeUser();

alert(user.ref().name); // John

이렇게 하면 user.ref()가 메서드가 되고 this는 . 앞의 객체가 되기 때문에 에러가 발생하지 않는다.

'Javascript > Node.js' 카테고리의 다른 글

커스텀 에러와 에러 확장  (0) 2021.09.27
try..catch와 에러 핸들링  (2) 2021.09.27
ESLint  (0) 2021.09.13
async/await  (0) 2021.09.13
프라미스(promise)  (0) 2021.09.13