객체지향프로그래밍 함수에 대해 학습을 하면서, 먼저 언제나 쓰인다는 'this'에 대해 정리해본다.
let user = {
name: "John",
age: 30
};
객체는 사용자(user), 주문(order)등과 같이 실제 존재하는 개체(entity)를 표현하고자 할때 생성된다.
객체, 사용자(user)의 현실적 쓰임은 '장바구니에서 물건 선택하기, 로그인하기, 로그아웃하기' 등의 action을 취한다.
let user = {
name: "John",
age: 30
};
user.sayHi = function() {
alert("안녕하세요!");
user.sayHi(); //안녕하세요!
위의 함수표현식에서 객체 property user.sayHi에 함수를 할당해 주었다.
이렇게 객체 property에 할당된 함수를 메서드(method)라고 부른다.
즉, user에 할당된 sayHi가 메서드이다.
let user = {
// ...
};
//함수 선언
function sayHi() {
alert("안녕하세요!");
};
//선언된 함수를 메서드로 등록
user.sayHi = sayHi;
usr.sayHi(); //안녕하세요!
메서드는 이미 정의된 함수를 위와 같이 이용해서 만들 수 있다.
//아래 두 객체는 동일하게 동작한다.
user = {
sayHi: function() {
alert("Hello");
}
};
//단축 구문을 사용하니 코드가 더 간단해진다.
user = {
sayHi() {
alert("Hello");
}
};
function를 생략해도 메서드를 정의할 수 있다.
하지만 좀더 깊이 알아봐야 할것은 일반적인 방법과 단축 구문을 사용한 방법이 완전히 동일하진 않다.
메서드는 객체에 저장된 정보에 접근할 수 있어야 제 역할을 할 수 있다. 모든 메서드가 그런 건 아니지만, 대부분의 메서드가 객체 프로퍼티의 값을 활용한다.
user.sayHi()
의 내부 코드에서 객체 user
에 저장된 이름(name)을 이용해 인사말을 만드는 경우가 이런경우에 속한다.
메서드 내부에서 this 키워드를 사용하면 객체에 접근할 수 있다.
이때 '점 앞'의 this
는 객체를 나타낸다. 정확히는 메서드를 호출할 때 사용된 객체를 나타낸다.
let user = {
name: "John",
age: 30,
sayHi() {
//'this'는 '현재 객체'를 나타낸다.
alert(this.name);
}
};
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
를 사용할 수 있다.
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
이다. 위 예시에선 obj
가 user
나 admin
를 참조했다.
객체가 없어도 함수를 호출할 수 있다.
function sayHi() {
alert(this);
}
sayHi(); // undefined
자바스크립트에서 this
는 런타임에 결정된다. 메서드가 어디서 정의되었는지에 상관없이 this
는 '점 앞의'객체가 무엇인가에 따라 '자유롭게' 결정된다.
이렇게 this
가 런타임에 결정되면 좋은 점도 있고 나쁜 점도 있다. 함수(메서드)를 하나만 만들어 여러객체에서 재사용할 수 있다는 것은 장점이지만, 이런 유연함이 실수로 이어질 수 있다는 것은 단점이다.
자바스크립트가 this
를 다루는 방식이 좋은지, 나쁜지는 우리가 판단할 문제가 아니다. 개발자는 this
의 동작 방식을 충분히 이해하고 장점을 취하면서 실수를 피하는 데에만 집중하면 된다.
object.doSomthig()
은 객체를 '행동'할 수 있게 해준다.this
로 객체를 참조한다.this
값은 런타임에 결정된다.
this
엔 값이 할당되지 않는다.object.method()
같이 '메서드'형태로 호출하면 this
는 object
를 참조한다.