Javascript의 this
는 다른 프로그래밍 언어의 this와 동작 방식이 다르다.
Javascript에서는 모든 함수에 this를 사용할 수 있다.
this는 함수 내에서 함수 호출 맥락(context)를 의미한다.
함수를 어떻게 호출하느냐에 따라서 this가 가리키는 대상이 달라진다는 의미이다.
this는 함수와 객체를 연결시켜주는 실질적인 연결점의 역할을 한다.
함수를 호출했을 때 this는 전역객체인 window를 가리킨다.
메소드 안에서 호출했을 때 객체의 소속인 메소드의 this는 객체를 가리킨다.
메서드는 객체에 저장된 정보에 접근하기 위해 대부분의 메서드가 객체 프로퍼티의 값을 활용한다.
메서드 내부에서 this
키워드를 사용하면 객체에 접근할 수 있다.
this
는 '.(점) 앞의' 객체(메서드를 호출할 때 사용된 객체)를 나타낸다.
그러나, this를 사용하지 않고 외부 변수 를 참조해 객체에 접근하는 것도 가능하나 예상치 못한 에러💢가 발생할 수 있으므로 '현재 객체'를 참조할 때는 'this'를 사용하는 것이 좋다.
let user = {
name: "Mimi",
age: 5,
sayHi() {
alert(user.name); // Error
}
};
let admin = user;
user = null; // user를 null로 덮어쓴다.
admin.sayHi(); // sayHi()는 user 객체를 참고하지 않고 에러가 발생한다.
this
값은 Runtime(프로그램이 동작하고 있을 때)에 결정된다.
함수를 선언할 때 this
를 사용할 수 있지만, 함수가 호출되기 전까지this
에 값이 할당되지 않는다.
this는 프로토타입에 영향을 받지 않는다.
메서드를 객체에서 호출했든 프로토타입에서 호출했든 상관없이 'this'는 '.(점) 앞의' 객체를 참조하기 때문에 동일한 함수라도 다른 객체에서 호출했다면 'this'가 참조하는 값이 달라진다.
let user = { name: "Mimi" };
let admin = { name: "Admin" };
function sayHi() {
alert(this.name);
}
// 별개의 객체에서 동일한 함수를 사용
user.f = sayHi;
admin.f = sayHi;
user.f(); // Mimi (this == user)
admin.f(); // Admin (this == admin)
화살표 함수는 일반 함수와는 달리 자신만의 this를 가지지 않는다.
화살표 함수에서 this를 참조하면, 화살표 함수가 아닌 외부 함수에서 this 값을 가져온다.
별개의 this가 만들어지는 것이 아닌 '외부 컨텍스트에 있는 this를 이용'하고 싶은 경우 화살표 함수가 유용하다.
객체의 로직을 그대로 물려 받는 또 다른 객체를 만들 수 있는 기능
Javascript의 객체는 [[Prototype]]
이라는 숨김 프로퍼티를 갖는다.
( __proto__ 는 [[Prototype]]의 getter(획득자)이자 setter(설정자) 이다.)
숨김 프로퍼티 값은 null이거나 다른 객체에 대한 참조가 된다.
다른 객체를 참조하는 경우 참조 대상을 '프로토타입(prototype)'이라 한다.
프로토타입 상속 : object에서 프로퍼티를 읽으려고 하는데 해당 프로퍼티가 없으면 자바스크립트는 자동으로 프로토타입에서 프로퍼티를 찾는 동작 방식
상속 프로퍼티(inherited property) : 프로토타입에서 상속받은 프로퍼티
프로토타입은 프로퍼티를 읽을 때만 사용하므로 프로퍼티를 추가, 수정, 삭제하는 연산은 객체에 직접해야 한다.
객체 rabbit에 메소드 walk를 직접 할당하고 rabbit.walk()를 호출하면 프로토타입에 있는 메소드가 실행되지 않고, 객체 rabbit에 추가한 메소드가 실행된다.
let anmial = {
eats: true,
walk() { // rabbit은 이제 해당 메소드를 사용하지 않는다.
}
};
let rabbit = {
__proto__: animal
};
rabbit.walk = function() { // 객체 rabbit에 메소드 walk를 직접 할당
alert("누구보다 빠르게 달리지 깡충깡충");
};
rabbit.walk(); // 누구보다 빠르게 달리지 깡충깡충
객체의 원형; 객체가 가지는 용도가 약속되어 있는 특수한 프로퍼티
prototype에 저장된 속성들은 생성자를 통해서 객체가 만들어질 때 그 객체에 연결된다.
위의 그림은 상속 관계를 그림으로 나타낸 것이다.
rabbit은 animal을, animal은 Object.prototype을, Object.prototype은 null을 상속받고 있다.
객체와 객체를 연결하는 체인의 역할을 하며, 이러한 관계를 prototype chain이라고 한다.
Sub와 Ultra가 prototype 체인으로 연결되어 있기 때문에 생성자 Sub를 통해서 만들어진 객체가 Ultra의 프로퍼티에 접근 가능하다.
※ Super.prototype = new Ultra();
vs Super.prototype = Ultra.prototype
'Super.prototype = new Ultra();'⭕는 Super는 부모인 Ultra의 속성과 메소드를 그대로 상속받을 때 사용되는데, Ultra.prototype의 원형으로 하는 객체가 생성되기 때문에 new Ultra()를 통해서 만들어진 객체에 변화가 생겨도 Ultra.prototype의 객체에는 영향을 주지 않는다.
그러나 'Super.prototype = Ultra.prototype'❌ 으로 하게되는 경우, Super.prototype의 값을 변경하면 그것이 Ultra.prototype도 변경되기 때문에 사용하면 안된다.