일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Next.js13
- leetcode
- JavaScript
- NPM
- 프론트엔드
- 자바스크립트
- 제로베이스
- next13
- 자바스크립트코딩테스트
- 리액트
- 자바스크립트 문제풀이
- CSS
- react
- 프로그래머스
- stack문제
- leetcode문제풀이
- 리액트쿼리
- Next
- Baekjoon
- 타입스크립트
- til
- HTML
- 자바스크립트 연결리스트
- 자바스크립트 알고리즘 문제
- 자바스크립트 문제 풀이
- lodash
- JS
- 자바스크립트 문제
- 알고리즘문제풀이
- 자바스크립트 알고리즘
- Today
- Total
코드노트
자바스크립트 this 이해하기 본문
생성자 함수를 예로들어보자.
생성자 함수 내부에서 프로퍼티, 메서드를 추가하려면 자신이 생성하는 인스턴스를 참조할 수 있어야한다.
* 참조할 수 있지만 함수 이름을 통해서 재귀적으로 참조하는 방식은 바람직하지 않은 방법 - this를 사용
this
- 자신이 속한 객체 또는 자신이 생성할 인스턴스를 가리키는 자기 참조 변수(self-referencting variable)
- this를 통해 자신이 속한 객체 또는 자신이 생성할 인스턴스의 프로퍼티 또는 메서드를 참조
- JS 엔진에 의해서 암묵적으로 생성
- 어느 코드에서나 참조 가능
- 함수 호출시 arguments객체와 this가 암묵적으로 함수 내부에 전달
- 지역 변수처럼 사용할 수 있다.
- this가 가리키는 값은? this바인딩, 함수 호출 방식에 의해 동적으로 결정
바인딩?
- 식별자와 값을 연결하는 과정을 의미
- this 바인딩 : this와 this가 가리키는 객체를 바인딩하는 것
this 예제
const traveler = {
first: "곽튜브",
sayHi() {
return `Hi ${this.first}`; // this는 메서드를 호출한 객체
},
};
console.log(traveler.sayHi()); // Hi 곽튜브
- 객체 리터럴 메서드 내부에서 this는 메서드를 호출하는 객체를 가리키고 있다. traveler
function Traveler(name) {
this.name = name; // this는 생성자 함수가 생성할 인스턴스
}
Traveler.prototype.sayHi = function () {
return `Hi ${this.name}`; // this는 생성자 함수가 생성할 인스턴스
};
const frist = new Traveler("곽튜브");
console.log(frist.sayHi()); // Hi 곽튜브
- 생성자 함수 내부에서는 생성자 함수가 생성할 인스턴스를 가리킨다.
- JS에서 this는 함수가 호출되는 방식에 따라 this에 바인딩되는 값이 동적으로 결정된다.
- 어떠한 함수라도 일반함수로 호출되면 this에 전역 객체가 바인딩 된다.
* (메서드 내에 정의한 중첩함수라도 일반함수라면 전역 객체)
- 중첩 함수 또는 메서드에게 전달한 콜백함수가 일반함수로 호출될 때 메서드 내에서 this가 전역 객체를 바인딩하는 것은 문제가 있다.
이 문제를 해결하려면!?
let value = 1;
const obj = {
value: 100,
foo() {
const here = this; // this를 변수에 할당 한다.
setTimeout(function () {
console.log(here.value); // 100
}, 100);
},
};
obj.foo();
- this바인딩을 변수에 할당해서 사용!
- 그 외에도 apply, call, bind를 사용할 수 있다.
- 화살표 함수를 사용해서 바인딩하면 this 바인딩을 일치시킬 수 있다.( 화살표 함수 내부의 this는 상위 스코프의 this를 가르킨다.)
메서드 호출 시 메서드 내부의 this는
메서드를 소유한 객체가 아닌 메서드를 호출한 객체에 바인딩 된다.
const traveler = {
name: "곽튜브",
sayHi() {
return `Hi ${this.name}`;
},
};
console.log(traveler.sayHi()); // Hi 곽튜브
const secondTraveler = {
name: "빠니보틀",
};
secondTraveler.sayHi = traveler.sayHi; // 메서드 할당
console.log(secondTraveler.sayHi()); // Hi 빠니보틀
- 메서드를 호출한 객체에 바인딩된 것을 볼 수 있다.
- 프로토타입에 추가하여 사용하게 되면 직접 호출할 수 있다. ( 호출 시점 )
생성자 함수 호출
- 생성자 함수내부의 this에는 생성자 함수가 생성할 인스턴스가 바인딩된다.
function Traveler(name) {
this.name = name;
this.sayHi = function () {
return `Hi ${this.name}`;
};
}
const first = new Traveler("곽튜브");
const second = new Traveler("빠니보틀");
console.log(first.sayHi()); // Hi 곽튜브
console.log(second.sayHi()); // Hi 빠니보틀
- 만약 new 연산자와 함께 생성자 함수를 호출하지 않으면 생성자 함수가 아니라 일반 함수로 동작
apply / call / bind
Function.prototype.XXX
- apply, call, bind 메서드는 함수가 상속 받아 사용
apply, call
function getThisBinding() {
console.log(arguments);
return this;
}
console.log(getThisBinding()); // window, vsCode에서는 Object
const thisArg = { a: 1 };
// apply, call 메서드는 함수를 호출하는 메서드
console.log(getThisBinding.apply(thisArg)); // { a: 1 }
console.log(getThisBinding.call(thisArg)); // { a: 1 }
// 인수로 전달하는 객체를 getTisBinding함수의 this로 바인딩
console.log(getThisBinding.apply(thisArg, [1, 2, 3]));
// [Arguments] { '0': 1, '1': 2, '2': 3 }
// { a: 1 }
console.log(getThisBinding.call(thisArg, 1, 2, 3));
// [Arguments] { '0': 1, '1': 2, '2': 3 }
// { a: 1 }
- apply, call의 기능은 함수를 호출하는 것
- 함수를 호출하면서 첫 번째 인수로 전달한 특정 객체를 호출한 함수의 this에 바인딩 한다.
- apply 메서드는 호출할 함수의 인수를 배열로 전달
- call 메서드는 호출할 함수의 인수를 쉼표로 구분한 리스트 형식으로 전달
- 위 코드를 참고하면 호출할 함수에 인수를 전달하는 방식만 다를 뿐 this로 사용할 객체를 전달하면서 함수를 호출하는 것은 동일
그럼 여기서 인수만 전달 해서 배열만 사용할 수 없을까?!!!
function convertArgsToArray() {
const arr = Array.prototype.slice.call(arguments);
// const arr = Array.prototype.slice.apply(arguments)
console.log(arr);
return arr;
}
convertArgsToArray(1, 2, 3); // [ 1, 2, 3 ]
- 위와 같이 사용 가능하다.
bind() 는 함수를 호출하지 않는다.
- 첫번째 인수로 전달한 값으로 this 바인딩이 교체된 함수를 새롭게 생성하여 반환
- 콜백함수의 this가 불일치하는 문제를 해결하는데 유용하게 사용 가능
- 함수를 호출하지 않으므로 명시적으로 호출 bind(this)
const traveler = {
name: "곽튜브",
foo(callback) {
setTimeout(callback.bind(this), 100);
},
};
traveler.foo(function () {
console.log(`Hi ${this.name}`); // Hi 곽튜브
});
- 콜백함수는 외부 함수를 도울때 헬퍼 함수 역할을 하기 때문에 내부의 this와 콜백 함수 내부의 this가 다르게 되면 문맥상 문제가 발생
- 콜백 함수 내부의 this를 외부 함수 내부의 this와 일치 시켜야할 때 사용할 수 있다.
함수 호출 방식 | this 바인딩 |
일반 함수 호출 | 전역 객체 |
메서드 호출 | 메서드를 호출한 객체 |
생성자 함수 호출 | 생성자 함수가 생성할 인스턴스 |
Function.prototype.apply / call / bind 메서드 간접 호출 | Function.prototype.apply / call / bind 메서드 첫번째 인수로 전달한 객체 |
'Code note > 자바스크립트' 카테고리의 다른 글
자바스크립트 클래스 정리 (0) | 2022.12.24 |
---|---|
자바스크립트 실행 컨텍스트 Execution context 정리 (0) | 2022.12.22 |
프로토타입 기반의 객체지향 언어, 자바스크립트 프로토타입 이해 (0) | 2022.12.19 |
자바스크립트 함수 객체 프로퍼티 정리 (0) | 2022.12.15 |
자바스크립트 Object 객체 생성자 함수 (0) | 2022.12.14 |