Notice
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- calender
- 웹사이트
- Timer
- DOM
- Typescript
- React
- 브라우저
- stopwatch
- darknode
- Calculator
- html
- mini_project
- CSS
- localStorage
- Project
- javascript
- todolist
Archives
- Today
- Total
이야기 정리
자바스크립트의 This란? 본문
자바스크립트를 공부하다보면 꼭 나오는 것 중 하나가 바로 this다. this는 호출에 따라 의미가 달라져 헛갈리기 때문에 간단한 예시들과 함께 this가 필요한 이유부터 살펴보려 한다.
this는 왜 필요할까?
먼저 생성자 함수를 생각해보자. 생성자 함수를 만드는 과정은 다음과 같다.
- 생성자 함수를 정의한다.
- 프로퍼티나 메서드를 추가한다.
- new를 사용해 인스턴스를 생성한다.
문제는 2번에서 프로퍼티나 메서드를 만들 때 3번에 있는 인스턴스의 값이 필요하다. 하지만 정의한 시점에서는 인스턴스를 가리키는 식별자를 알 수 없다. 이 때문에 this가 필요하다.
// 1,2번 과정 : 여기서는 ??? 안에 뭐가 들어올지 알 수가 없다.
function Obj(x, y) {
???.x = x
???.y = y
???.add = function () {
return x+y
}
}
// 3번과정 : 이때 인스턴스를 생성한다.
const obj = new Obj(5, 5)
console.log(obj.add())
그렇다면 this란 무엇일까?
- 함수 내에서 사용되는 변수(자기 참조 변수)이며, 함수 호출 방식에 따라 의미가 달라진다. (자바스크립트만의 특징!)
- 즉, this는 함수가 소속되어 있는 객체를 가리킨다!!
- this가 가리키는 값을 결정 짓는 것을 this 바인딩이라고 한다.
바인딩이란?
식별자와 값을 연결하는 과정
const a(식별자) = 1(값)
예를 들어, 위처럼 변수를 선언했을 때 코드는 a(식별자)와 1(값)을 바인딩해주는 것이다.
함수 호출방식과 this 바인딩
1. 일반 함수 호출
- 전역 객체(window)가 호출된다.
- 일반 호출이면 중첩 함수, 콜백함수도 전역 객체가 호출된다.
function foo() {
console.log(this) //window
function bar() {
console.log(this) //window
}
bar()
}
foo()
2. 메소드 호출
- 객체 안에 프로포티를 함수로 하면 메소드가 된다.
- 메소드가 소속된 객체(. 앞에 있는 객체)가 바로 this다.
예제1 : 다른 객체에서 호출하기
const obj = {
name : 'kim',
getName : function () {
console.log(this) // {name: 'kim', getName: ƒ}
console.log(this.name) //kim
}
}
const obj2 = {
name : 'park',
getName : obj.getName //{name: 'park', getName: ƒ}, park
}
// obj2에서 호출했기 때문에 park이 나타나게 된다.
obj2.getName()
주의하기!!!
메서드를 일반 함수로 호출하면 마찬가지로 전역객체가 호출된다.
const obj = {
name : 'kim',
getName : function () {
console.log(this) // {name: 'kim', getName: ƒ}
console.log(this.name) //kim
}
}
// 일반 호출이기 때문에 window로 나타난다.
const name = obj.getName
name() // window
예제 2 : 중첩함수
중첩함수를 일반함수로 호출하면 마찬가지로 전역객체가 호출된다. 아래 예제를 해결하는 방법은 2가지가 있다.
const obj = {
name : 'kim',
age: 20,
getName : function () {
console.log(this) // {name: 'kim', age: 20, getName: ƒ}
console.log(this.name) //kim
// 중첩함수는 일반호출을 했기 때문에 전역 객체가 호출된다.
function getAge() {
console.log(this) // window
console.log(this.age) // undifned
}
getAge()
}
}
obj.getName()
해결법 : 화살표 함수나 변수 사용하기
const obj = {
name : 'kim',
age: 20,
getName : function () {
console.log(this) // {name: 'kim', age: 20, getName: ƒ}
console.log(this.name) //kim
// 방법 1 : 화살표함수 사용
const getAge = () => {
console.log(this) // {name: 'kim', age: 20, getName: ƒ}
console.log(this.age) // 20
}
getAge()
// 방법 2 : 변수 사용
const then = this
function getAge2() {
console.log(then) // {name: 'kim', age: 20, getName: ƒ}
console.log(then.age) // 20
}
getAge2()
}
}
obj.getName()
3. 생성자 함수
- new와 함께 생성된다.
- 이때, 새로 생성되는 인스턴스(객체)가 this가 된다.
function Obj(name) {
this.name = name
this.getName = function () {
return this.name
}
}
const obj = new Obj('kim')
console.log(obj.getName()) // kim
4. 객체로서의 함수 : .apply, .call, .bind
함수는 객체이기 때문에 메서드를 사용할 수 있다.
this의 값을 고정시키기 위한 메서드는 총 3종류로 apply와 call은 함수를 호출하지만, bind는 호출하지 않는다는 차이점이 있다. 먼저 함수를 호출하는 apply와 call에 대해 알아보자.
.apply, .call
- 첫인자가 this가 되며, 객체를 this로 전달한다.
- 인수를 전달하는 방식만 다를 뿐, this로 사용할 객체를 전달하면서 함수를 호출한다는 점은 동일하다.
//사용법
함수이름.apply({객체이름 : 객체값}, [인수 리스트]);
함수이름.call({객체이름 : 객체값}, 인수1, 인수2, 인수3);
주로 arguments 등의 유사 배열 객체에 배열 메서드를 사용하는 경우에 이용한다.
function obj() {
console.log(this) // {name: 'kim'}
console.log('Hi, ' + this.name) // Hi, kim
}
console.log(obj.apply({name: 'kim'}))
function obj2(arr) {
console.log(arguments) //[1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
const a = Array.prototype.slice.call(arguments) // [1, 2, 3]
const b = a.map(a => this.number + a)
return b
}
console.log(obj2.apply({number: 10}, [1,2,3])) // [11, 12, 13]
.bind
- apply, call과 달리 함수를 실행시키지 않는다. 때문에 별도로 실행시켜줘야한다.
function obj() {
console.log(this) // {name: 'kim'}
console.log('Hi, ' + this.name) // Hi, kim
}
// 함수를 실행시키지 않는다.
console.log(obj.bind({name: 'kim'})) // ƒ obj()
// 별도로 함수를 실행시켜야한다.
console.log(obj.bind({name: 'kim'})()) // {name: 'kim'}, Hi, kim
예제 : 다음처럼 함수의 일반 호출이나, 중첩함수에서 사용할 수 있다.
function getName () {
console.log(this) // {name: 'kim', age: 20, getName: ƒ}
console.log(this.name) //kim
const binding2 = getAge.bind(this)
function getAge() {
console.log(this) // {name: 'kim', age: 20}
console.log(this.age) // 20
}
binding2()
}
const binding = getName.bind({name: 'kim', age: 20})
binding()
주의하기!!!
화살표 함수를 사용하면 함수가 속해있는 곳의 상의 this를 계승한다. bind를 사용할 수 없다.
참조
모던자바스크립트 Deep Dive - 이웅모 342p~358p
https://www.youtube.com/watch?v=4ACSJlzJjJs&feature=youtu.be
'개발공부 > JavaScrit' 카테고리의 다른 글
[자바스크립트] 엘리먼트의 위치 값 구하기 - getBoundingClientRect(), offsetTop (0) | 2023.03.28 |
---|---|
무한반복하기 - while문, do while문 (0) | 2023.02.14 |
새로고침을 해도 유지되는 다크모드 - localStorage() (0) | 2023.02.01 |
문자열, 숫자열을 배열로 반환하기 - split(), toString(), Number() (0) | 2023.01.18 |
간단하게 대/소문자로 바꾸기 - toUpperCase(), toLowerCase() (0) | 2023.01.13 |
Comments