반응형
JavaScript에서 this
JavaScript에서 this는 객체를 가르키는 키워드로, 현재 실행 중인 함수의 문맥(context)을 가르킨다.
this가 가르키는 대상은 함수 호출 방식에 따라 달라진다.
01) 전역 범위
- 전역 범위에서 this는 기본값으로 전역 객체를 의미
- 브라우저에서 전역 객체는 window 객체로, 브라우저 환경에서 제공되는 다양한 API를 제어할 수 있음
console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
02) 함수 호출
- 일반 함수에서 this는 기본적으로 전역 객체를 가리킴
- 호출한 객체가 없으므로 window 객체가 출력됨
function printThis() {
console.log(this);
}
printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
03) 메서드 호출
- 객체 안에서 메서드를 호출할 때, this는 해당 객체(=person)를 가리킴
let person = {
name: "peazh",
age: 20,
printThis: function () {
console.log(this);
},
};
person.printThis(); // { name: "peazh", age: 20, hello: f }
function printThis() {
console.log(this);
}
let person1 = {
name: "여름1",
printThis: printThis,
};
person1.printThis(); // {name: '여름1', printThis: ƒ}
let person2 = {
name: "여름2",
printThis: printThis,
};
person2.printThis(); // {name: '여름2', printThis: ƒ}
let person3 = {
name: "여름3",
printThis: printThis,
};
person3.printThis(); // {name: '여름3', printThis: ƒ}
🔻예외 경우
let person = {
name: "peazh",
age: 20,
printThis: function () {
console.log(this);
},
};
let printThis = person.printThis;
printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
- 객체의 메서드를 변수에 할당한 후 호출하면, 메서드와 객쳉의 연결이 끊어져 this는 전역 객체를 가리키게 됨
- 그래서 메서드 호출이 아닌 일반 함수 호출처럼 동작함
04) 화살표 함수
- 자신이 선언된 외부 스코프에서 this를 그대로 상속받음
- 정적으로 바인딩(선언된 시점의 스코프에 따라 결정)되며, 화살표 함수의 내부 this는 변하지 않음
🔻일반 함수를 사용
let person = {
name: "peazh",
age: 20,
hello: function () {
setTimeout(function () {
console.log(this)
}, 1000);
},
};
person.hello(); //Window {window: Window, self: Window, document: document, name: '', location: Location, …}
- setTimeout 같은 비동기 함수의 콜백으로 전달된 함수는 특별히 다른 바인딩이 없는 한 전역 스코프에서 실행됨
- 콜백 함수는 객체의 메서드로 호출된 것이 아니라 단독으로 호출된 것으로, this가 전역 객체를 참조함
🔻일반 함수를 화살표 함수로 변경
let person = {
name: "peazh",
age: 20,
hello: function () {
setTimeout(() => {
console.log(this);
}, 1000);
},
};
person.hello(); // {name: 'peazh', age: 20, hello: ƒ}
- this는 화살표 함수를 포함하고 있는 외부 스코프 person 객체를 가리킴
🔻화살표 함수를 사용하면 안되는 경우
let person = {
name: "peazh",
age: 20,
hello: () => {
console.log(this);
},
};
person.hello(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
- hello의 외부 스코프는 전역 스코프이기 때문에, 전역 스코프의 this인 window 객체를 반환
- 이와 같은 경우에는 화살표 함수보다는 일반 함수를 사용해야 함
05) 이벤트 핸들러
🔻일반 함수
let btn = document.querySelector("button");
btn.addEventListener("click", function () {
console.log(this); // <button id="btn">버튼</button>
console.log(this === btn); // true
});
- 일반 함수에서 this는 호출되는 DOM 요소(이벤트가 발생한 대상)를 가리킴
🔻화살표 함수
let btn = document.querySelector("button");
btn.addEventListener("click", () => {
console.log(this); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
});
- 이벤트 핸들러로 전달될 함수의 this는 호출 시점에 결정되는데, 화살표 함수는 그 자체로는 this를 바인딩하지 않기 때문에 전역 객체를 참조함
06) 엄격 모드
- 엄격 모드(Strict Mode)에서는 기본값이 전역 객체가 아닌 undefined로 설정되어, 더욱 엄격하게 검사함
🔻non strict mode
function printThis() {
console.log(this);
}
printThis(); // Window {window: Window, self: Window, document: document, name: '', location: Location, …}
🔻strict mode
'use strict'
function printThis() {
console.log(this);
}
printThis(); // undefined
07) bind 메서드 사용
- bind를 사용하여 this의 값을 명시적으로 설정할 수 있음
- 원하는 함수에 바인드 메서드를 호출한 뒤 객체를 파라미터로 전달해주면 됨
function printThis() {
console.log(this);
}
// this를 마음대로 변경하기
let person = {
name: "한여름",
};
let printThis1 = printThis.bind(person);
printThis1(); // {name: '한여름'}
🔻주의사항
let person1 = {
name: "한여름",
};
let person2 = {
name: "최여름",
};
let printThis1 = printThis.bind(person1);
let printThis2 = printThis1.bind(person2);
printThis2(); // {name: '한여름'}
- bind는 한 번 바인딩된 함수의 this 값을 다시 바인딩할 수 없음
- 그래서 printThis1을 person1에 바인딩한 후 다시 바인딩을 시도해도, '최여름'이 아닌 '한여름'이 출력됨
🔻bind 메서드 사용 전
let person = {
name: "peazh",
age: 20,
hello: function () {
setTimeout(function () {
console.log(this.name);
console.log(this.age); // undefined
}, 1000);
},
};
person.hello();
- setTimeout에서의 콜백 함수가 일반 함수로 호출되기 때문에 this는 전역 객체를 가리킴
- 그래서 this.name, age는 undefined가 출력됨
🔻bind 메서드 사용 후
let person = {
name: "peazh",
age: 20,
hello: function () {
setTimeout((function () {
console.log(this.name); // peazh
console.log(this.age); // 20
}).bind(this), 1000);
},
};
person.hello();
- bind를 사용하여 this를 명시적으로 person 객체로 고정
반응형
댓글