[Javascript] 객체: 메서드와 this

2025. 6. 11. 09:00Javascript/Javascript

728x90
반응형

 

 

 

객체는 실재하는 개체(entity)를 표현하고자 할 때 생성하며 자바스크립트에서는 객체의 프로퍼티에 함수를 할당해 행동할 수 있는 능력을 부여해 준다.

 

let user = {
  name: "John",
  age: 30
};

user.sayHi = function() {
  alert("안녕하세요!");
};

user.sayHi(); // 안녕하세요!

 

위 예세어세는 함수 표현식으로 함수를 만들고 객체 프로퍼티 user.sayHi에 함수를 할당해 주었다. 이제 객체에 할당된 함수를 호출하면 user가 인사를 해줄 것이다. 이처럼 객체 프로퍼티에 할당된 함수를 메서드(method)라고 부른다. 메서드는 아래와 같이 이미 정의된 함수를 이용해서 만들 수도 있다.

let user = {
  // ...
};

// 함수 선언
function sayHi() {
  alert("안녕하세요!");
};

// 선언된 함수를 메서드로 등록
user.sayHi = sayHi;

user.sayHi(); // 안녕하세요!

 

 

 

메서드 단축 구문

 

객체 리터럴 안에 메서드를 선언할 때 사용할 수 있는 단축 문법이 있다.

// 아래 두 객체는 동일하게 동작한다.

user = {
  sayHi: function() {
    alert("Hello");
  }
};

// 단축 구문
user = {
  sayHi() { // "sayHi: function()"과 동일.
    alert("Hello");
  }
};

 

위와 같이 function을 생략해도 메서드를 정의할 수 있다. 물론 일반적인 방법과 단축 구문이 완전히 동일한 기능을 하지는 않다. 객체 상속에 관련된 미묘한 차이가 존재하는데 여기에 대해서는 별도 포스팅으로 작성할 예정.

 

 


 

 

메서드와 this

 

메서드는 객체에 저장된 정보에 접근할 수 있어야 제 역할을 할 수 있다. 모든 메서드가 그런 건 아니지만 대부분의 메서드가 객체 프로퍼티의 값을 활용한다. 예를 들면 user.sayHi()의 내부 코드에서 객체 user에 저장된 name을 이용해 인사말을 만드는 것.

 

메서드 내부에서 this 키워드를 사용하면 객체에 접근할 수 있다. 이때 this는 객체를 가리킨다. 정확히는 메서드를 호출할 때 사용된 객체를 나타낸다고 할 수 있다.

 

let user = {
  name: "John",
  age: 30,

  sayHi() {
    alert(this.name); // 'this'는 '현재 객체'를 나타낸다.
  }

};

user.sayHi(); // John

 

위 예시에서 user.sayHi()가 실행되는 동안 this는 user를 나타낸다. 그리고 아래와 같이 this를 사용하지 않고 외부 변수에 참조해 객체에 접근하는 것도 가능하다.

let user = {
  name: "John",
  age: 30,

  sayHi() {
    alert(user.name); // 'this' 대신 'user'를 이용함
  }

};

 

그런데 이렇게 외부 변수를 사용해 객체를 참조하면 예상치 못한 오류가 발생할 수 있다. user를 복사해 다른 변수에 할당(admin = user)하고 user는 전혀 다른 값으로 덮어썼다고 가정해 보자. 그러면 sayHi()는 원치 않는 값(null)을 참조하게 될 것이다.

let user = {
  name: "John",
  age: 30,

  sayHi() {
    alert( user.name ); // Error: Cannot read property 'name' of null
  }

};


let admin = user;
user = null; // user를 null로 덮어씀.

admin.sayHi(); // sayHi()가 엉뚱한 객체를 참고하면서 에러가 발생

 

alert 함수가 user.name 대신 this.name을 인수로 받았다면 이와 같은 오류는 발생하지 않았을 것이다.

 

 


 

 

this

자바스크립트의 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

 

규칙은 간단하다. obj.f()를 호출했다면 this는 f()를 호출하는 동안의 obj인 것이다.

 

 

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

function sayHi() {
  alert(this);
}

sayHi(); // undefined

 

위와 같은 코드를 strict mode에서 실행하면 this에는 undefined가 할당된다. 그러나 엄격 모드가 아닐 때에는 this가 전역 객체를 참조한다. 브라우저 환경에서는 window라는 전역 객체를 참조하는 것이다. 이러한 동작 차이는 "use strict"가 도입된 배경이기도 하다. use strict에 대해서는 아래 글 참조.

 

[Javascript] use strict

Javascript는 꽤 오랫동안 호환성 이슈 없이 발전해 왔다. 기존의 기능을 변경하지 않으면서 새로운 기능들이 추가되었던 것이다. 덕분에 기존에 작성한 코드는 절대 망가지지 않는다는 장점이 있

developing-move.tistory.com

 

이런 식의 코드는 대개 실수로 작성되는 경우가 많다. 함수 본문에 this가 사용되었다면 객체 컨텍스트 내에서 함수를 호출할 것이라고 예상하면 된다.

 

 

다른 언어를 사용하다 자바스크립트로 넘어온 개발자는 이러한 this를 혼동하기 쉽다. this는 항상 메서드가 정의된 객체를 참조할 것이라고 착각하는 것이다. 이러한 개념을 bound this라고 한다.

 

앞서 자바스크립트에서 this는 런타임에 결정된다고 했다. 메서드가 어디서 정의되었는지에 상관없이 this는 점 앞의 객체가 무엇인지에 따라 자유롭게 결정되는 것이다. 이렇게 this가 런타임에 결정되면 함수(메서드)를 하나만 만들어 여러 객체에서 재사용할 수 있다는 장점이 있는 반면 이러한 유연함이 실수로 이어질 수 있다는 단점이 있다.

 

자바스크립트가 this를 다루는 방식이 좋은지 나쁜지는 개발자가 판단할 몫이 아니다. 우리는 this의 동작 방식을 충분히 이해하고 장점을 취하면서 실수를 피하는 데에만 집중하면 된다.

 

 

 

this가 없는 화살표 함수

 

화살표 함수는 일반 함수와는 달리 고유한 this를 가지지 않는다. 화살표 함수에서 this를 참조하면 화살표 함수가 아닌 평범한 외부 함수에서 this 값을 가져온다. 아래 예시에서 arrow()의 this는 외부 함수 user.sayHi()의 this가 된다.

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

user.sayHi(); // John

 

별개의 this가 만들어지는 건 원하지 않고 외부 컨텍스트에 있는 this를 이용하고 싶은 경우에는 화살표 함수가 유용하다.

 

 

 

 

 

728x90
반응형