0. this
this는 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수이다.
this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티나 메서드를 참조할 수 있다.
this는 자바스크립트 엔진에 의해 암묵적으로 생성되며, 코드 어디서든 참조할 수 있다.
단 this가 가리키는 값, 즉 this 바인딩은 함수 호출 방식에 의해 동적으로 결정된다.
1. this 바인딩이란?
바인딩이란 식별자(변수)와 값(원시 값 또는 객체)을 연결하는 과정을 의미한다.
예를 들어, 변수 선언은 변수 이름(식별자)과 확보된 메모리 공간의 주소를 바인딩하는 것이다.
this 바인딩은 this(키워드로 분류되지만 식별자 역할을 한다)와 this가 가리킬 객체를 바인딩하는 것이다.
2. this 바인딩은 함수 호출에 따라 달라짐(선언 X)
자바스크립트에서 this 는 함수 실행컨텍스트가 생성될 때 함께 결정된다
-> 실행컨텍스트가 언제 생성이 되는것인지? 실행컨텍스트는 함수가 호출이 될 때 생성된다.
-> 즉, this는 함수를 호출할 때 결정된다.
-> 함수를 어떤 방식으로 호출하느냐에 따라 this 바인딩 값이 달라진다.
구체적으로, 프로그램이 실행되면 자바스크립트는 전역 코드를 평가해서 전역실행 컨텍스트를 만들고, 함수가 실행(호출)이 되면 전역 실행컨텍스트는 멈추고 함수 실행컨텍스트를 생성하는데, 이 타이밍에 this 바인딩 값이 결정된다.
1) 전역에서 호출 되거나, 일반,콜백함수 내부에서 사용되면 window 전역객체 출력
// 전역에서 호출
console.log(this) //Window
function myFunc(){
console.log(this)
}
myFunc() //Window
2) 객체 메서드 내부에서는 해당 메서드를 소유한 객체, 즉 해당 메서드를 호출한 객체에 바인딩됨
아래 예제처럼 객체 안에 들어간 함수를 메서드라고 한다.
var obj = {
data:'Kim',
myMethod : function(){
console.log('안녕')
}
}
obj.myMethod() //안녕
메서드 안에 this를 쓰면 내가 만든 객체가 출력된다.
var obj1 = {
data:'Kim',
myMethod : function(){
console.log(this)
}
}
obj1.myMethod() // {data: 'Kim', myMethod: ƒ}
3) 이벤트 핸들러에서 this는 이벤트 객체를 발생시킨 DOM 을 의미
4) 화살표함수에서의 this (렉시컬 this)
const cat ={
name:'meow',
foo1:function(){
const foo2 = function(){
console.log(this.name)
}
foo2()
}
}
cat.foo1() // undefined
cat.foo1() 메소드 호출 시 내부 함수 foo2가 실행됨
함수가 호출 됐으므로 foo2 내부의 this는 지정되지 않아서 곧 전역 객체(window)를 가리킨다.
전역 객체에 name이란 속성은 존재하지 않아서 undefined가 뜬다.
const cat ={
name:'meow',
foo1:function(){
const foo2 = ()=>{
console.log(this.name)
}
foo2()
}
}
cat.foo1() //'meow'
위 코드와 달라진 점은 cat 객체의 내부 함수 foo2 가 화살표 함수로 선언됐다는 점 뿐이다.
그런데 이번엔 우리가 의도한대로 'meow'가 잘 출력이되었다.
이게 가능한 이유는 화살표 함수에는 ⭐️this가 아예 없기 때문⭐️입니다. 즉, function으로 선언한 함수를 실행할 땐 this가 존재하긴 하지만 값을 지정하지 않는데, 화살표 함수로 선언한 함수에는 this가 없습니다.
JavaScript에서는 어떤 식별자(변수)를 찾을 때 현재 환경에서 그 변수가 없으면 바로 상위 환경을 검색한다.(스코프체인) 그렇게 점점 상위 환경으로 타고 타고 올라가다가 변수를 찾거나 가장 상위 환경에 도달하면 그만두게 되는 것이다. 화살표 함수에서의 this 바인딩 방식도 이와 유사합니다. 화살표 함수에는 this라는 변수 자체가 존재하지 않기 때문에 그 상위 환경에서의 this를 참조하게 된다.
✅더 정확히는, function으로 선언한 함수가 메소드로 호출 되냐 함수 자체로 호출 되냐에 따라 동적으로 this가 바인딩되는 반면, 화살표 함수는 선언될 시점에서의 상위 스코프가 this로 바인딩됩니다.
화살표함수는 일반함수와 다르게 언제나 상위 스코프의 this를 가리키는걸 렉시컬 this라고 한다.
화살표 함수는 this 바인딩이 아니라 this 참조이다!! (상위 스코프 this를 가리키니까 정확히 말하면 this 바인딩이 아니라 this 참조인것이다)
※주의)
아래 예제처럼 화살표 함수로 메소드를 정의하는것은 혼란을 불러일으킬 수도 있다.
메소드로 정의한 화살표 함수 내부의 this는 메소드를 소유한 객체, 즉 메소드를 호출한 객체를 가리키지 않고 상위 컨택스트인 전역 객체 window를 가리킨다. 따라서 화살표 함수로 메소드를 정의하는 것은 바람직하지 않다.
const person = {
name: 'Lee',
sayHi: () => console.log(`Hi ${this.name}`)
};
person.sayHi(); // Hi undefined
이와 같은 경우는 메소드를 위한 단축 표기법인 ES6의 축약 메소드 표현을 사용하는 것이 좋다.
// Good
const person = {
name: 'Lee',
sayHi() { // === sayHi: function() {
console.log(`Hi ${this.name}`);
}
};
person.sayHi(); // Hi Lee
5) 생성자 함수의 this는 미래에 생성할 인스턴스
// 생성자 함수 예제
function Person(name, age) {
this.name = name;
this.age = age;
}
// 생성자 함수를 사용하여 객체 생성
const person1 = new Person('John', 30);
console.log(person1); // { name: 'John', age: 30 }
const person2 = new Person('Jane', 25);
console.log(person2); // { name: 'Jane', age: 25 }
참고자료
https://github.com/junh0328/prepare_frontend_interview/blob/main/js.md#this
'프론트엔드 개발 > JavaScript' 카테고리의 다른 글
자바스크립트) 일급객체 (0) | 2023.06.12 |
---|---|
자바스크립트) 생성자 함수 (0) | 2023.06.08 |
자바스크립트) 클로저 끝장 정리 (0) | 2023.06.05 |
자바스크립트) 실행컨텍스트, 호이스팅, 렉시컬환경, 스코프체인 (1) | 2023.06.04 |
자바스크립트) 스코프 (0) | 2023.06.01 |