Javascript/[인프런] 자바스크립트 중고급
[자바스크립트 중고급] 6. this
minha62
2022. 2. 18. 04:17
this 개요
- 키워드
- obj.name() 형태로 호출한 함수(메소드)에서 this로 인스턴스(오브젝트)를 참조
- 실행 콘텍스트의 this 바인딩 컴포넌트에 바인딩
this와 글로벌 오브젝트
- 글로벌 오브젝트에서 this는 글로벌 오브젝트 참조
- this와 window 오브젝트
- window는 JS에서 만든 것이 아니며 글로벌 오브젝트의 스코프도 아님
- window와 글로벌 오브젝트를 같은 선상에서 사용
- Hosw 오브젝트 개념 적용
- 글로벌 오브젝트에 코드 작성
window.onload = function(){
// 안이 아니라 밖에 코드 작성
}; - this가 window 참조
log(this === window);
// true
- this로 글로벌 변수 사용
var value = 100;
log(this.value);
// 100
- window로 글로벌 변수 사용
var value = 100;
log(window.value);
// 100
- this.value = 100; 형태로 값 할당
this.value = 100;
log(window.value);
// 100
this와 window 오브젝트
- window.onload = function(){
// 여기에 코드 작성
} - this가 window 참조
window.onload = function(){
log(this === window);
};
// true
- this로 로컬(지역) 변수 사용
window.onload = function(){
var value = 100;
log(this.value);
};
// undefined
- this.value = 100; 형태로 값 할당
window.onload = funciton(){
this.value = 100;
log(window.value);
};
// 100
this 참조 범위
this와 strict 모드
- 오브젝트.함수이름() 형태로 함수 호출
- 글로벌 오브젝트는 오브젝트 이름이 없으므로 함수 이름만 작성하여 호출
- strict 모드에서는
- window.book()처럼 book() 앞에 window를 글로벌 오브젝트로 작성
- 함수 앞에 오브젝트를 작성하지 않으면
- this 바인딩 컴포넌트에 undefined가 설정되므로
- this로 window를 참조할 수 없음
function book(){
"use strict";
return this;
};
var result = book();
log(result);
// undefined
function book(){
"use strict";
return this;
};
var obj = window.book();
log(obj === window);
// true
this 참조 오브젝트
var book = {
point: 100,
memeber: {
point: 200,
get: function(){
log(this === book.memeber);
log(this.poin);
}
}
};
book.memeber.get();
// true
// 200
- this가 참조하는 오브젝트
- 마지막 줄에서 book.memeber.get() 호출
- this가 member 오브젝트 참조
- book은 get()을 호출하는 경로 역할
- console.log(this === book.memeber);
- [실행 결과]에 true가 출력되며 this가 book.member를 참조하기 때문
- 즉, thiw 바인딩 컴포넌트에 book.memeber 오브젝트가 설정됨
- console.log(this.point);
- this가 book.memeber를 참조하므로
- book.point 값인 100을 출력하지 않고 book.member의 200을 출력
정리 시간
var book = {
value: 123,
get: function() {
var value = 456;
log(this === window);
log(this.value);
}
};
var fn = book.get;
fn();
// true
// undefined
- 마지막 줄에서 fn()을 호출하면 book.get() 함수가 호출됨
- console.log(this === window)에서 true가 출력되는 논리를 제시하시오.
- console.log(this.value)에서 undefined가 출력되는 논리를 제시하시오.
this와 인스턴스
- 인스턴스 목적?
- 인스턴스마다 고유 값 유지
- 인스턴스에서 this의 목적?
- this로 인스턴스를 참조하여
- this.name 형태로 프로퍼티에 접근
- __proto__ 프로퍼티 접근
- prototype에 연결된 프로퍼티가 인스턴스의 __proto__에 첨부되며
- this.method() 형태로 __proto__에 첨부된 method() 호출
var book = {};
book.Point = function(point){
this.point = point;
};
book.Point.prototype.getPoint = function(){
log(this.point);
};
var obj = new book.Point(100);
obj.getPoint();
// 100
- var obj = new book.Point(100);
- book.Point 인스턴스를 생성
- this.point = point;
- this가 생성한 인스턴스를 참조하므로 point는 인스턴스 프로퍼티가 됨
- 이 논리로 인스턴스마다 프로퍼티 이름과 값을 유지할 수 있음
- obj.getPoint();
- obj 인스턴스의 getPoint() 메소드 호출
- console.log(this.point);
- obj.getPoint()로 호출, this가 obj 참조
- obj는 book.Point 인스턴스
- book.Point 인스턴스의 point 값 출력
this와 call()
- getTotal.call(this, 10, 20)
- 10과 20을 파라미터 값으로 넘겨줌
- 첫 번째는 파라미터 값으로 넘어가지 않고 두 번째부터 넘어감
- 첫 번째 파라미터에
- 호출된 함수에서 this로 참조할 오브젝트 작성
- this 이외에 다른 오브젝트 사용 가능
this 사용
"use strict";
var value = 100;
function get(param){
return param + this.value;
};
var result = get.call(this, 20);
log(result);
// 120
- window.onload = function(){
// onload 밖에 코드를 작성
// 즉, 글로벌 오브젝트에서 실행
};
- get.call(this, 20)
- 첫 번째 파라미터에 this 작성
- return param + this.value;
- this가 글로벌 오브젝트를 참조하므로
- (var value = 100)을 사용
call(()을 사용하지 않고
3. return param + this.value;
- get(20)으로 호출하면 this가 undefined를 참조하므로 에러 발생
Object 사용
var get = function(value){
return this.base + this.rate + value;
};
var value = {base: 20, rate: 30};
var result = get.call(value, 50);
log(result);
// 650
- var result = get.call(value, 50);
- call()의 첫 번째에 Object 작성
- 50은 파라미터 값
- return this.base * this.rate + value;
- this가 {base: 20, rate: 30}을 참조
- 20 * 30 + 50
- this로 참조할 오브젝트를 변경할 수 있는 것이 call()의 특징
숫자 작성
function get(){
return this.valueOf();
};
var result = get.call(123);
log(result);
// 123
- var result = get.call(123);
- this가 오브젝트를 참조하므로
- 숫자(123)를 작성하면 에러가 발생해야 하지만
- 값(123) 타입에 해당하는
- Number 인스터스를 생성하고
- 123을 프리미티브 값으로 설정
- this가 Number 인스턴스를 참조
this 참조 변경
var book = {
value: 123,
point: {
value: 456,
get: function () {
log(this.value);
}
}
};
book.point.get.call(book);
book.point.get.call(book.point);
// 123
// 456
- book.point.get.call(book);
- book.point의 get() 호출
- get()에서 this로 book 오브젝트 참조
- this.value가 book.alue이므로 123 출력
- book.point.get.call(book.point);
- book.point의 get() 호출
- get()에서 this로 book.point 오브젝트 참조
- this.value가 book.point.value이므로 456 출력
this와 apply()
- getTotal.apply(this, [10, 20])
- 함수 호출 방법은 call()과 같으며 파라미터가 배열인 것이 다름
- [10, 20]을 파라미터 값으로 넘겨줌
- 두 번째 파라미터 수가 유동적일 때 사용
- call()은 파라미터 수가 고정일 때 사용
this와 arguments
var obj = {0: 10, 1: 20, 2: 30};
var data = [4, 5, 6];
function get(){
for (k = 0; k < arguments.length; k++){
log(arguments[k] + this[k]);
};
};
get.apply(obj.data);
// 14
// 25
// 36
- get.apply(obj, data);
- get() 함수에서 obj를 this로 참조
- 두 번째 파라미터 [4, 5, 6]을
- arguments를 사용하여 계산
- 파라미터 수가 유동적이므로 arguments가 편리
- get()으 함수 코드는 바뀌지 않으며
- 넘겨 주는 파라미터 값과
- this로 참조할 오브젝트만 변경하면 됨
- Array-like 형태
this와 콜백 함수
var obj = {value: 100};
var data = [5, 6, 7];
function callback(element, index, data){
return element + this.value;
};
function get(data){
return data.map(callback, obj);
};
var result = get(data);
log(result);
// [105, 106, 107]
- ES5의 map(), forEach()처럼
- 콜백 함수가 있는 메소드는 두 번째 파라미터에 this로 참조할 오브젝트를 작성(option)
- function callback(element, index, data){
return element + this.value;
};- map()에서 호출하는 콜백 함수
- return data.map(callback, obj);
- map()의 두 번째 파라미터에 obj를 작성
- callback()에서 obj를 this로 참조
- map()의 코드는 바꾸지 않고
- obj 값과 data 파라미터 값만 바꾸면 됨
this와 bind()
bind()
- 두 번에 나누어 처리
- function 오브젝트 생성
- 생성항 function 오브젝트를 함수로 호출
- 파라미터
- 1번째 파라미터에 함수에서 this로 참조할 오브젝트
- 2번째 파라미터에 호출된 함수의 파라미터 값
- 생성한 function을 호출할 때에도 파라미터 작성 가능
- 두 개의 파라미터를 병합하여 사용
function 오브젝트 생성, 호출
var book = {
point: 123,
get: function() {
return this.point;
}
};
var obj = book.get.bind(book);
log(typeof obj);
var result = obj();
log(result);
// function
// 123
- var obj = book.get.bind(book);
- book.get()을 호출하지 않고
- function 오브젝트를 생성하여 반환
- 생성한 function 오브젝트를 생성한 오브젝트의 [[TargetFunction]]에 설정
- 처리를 나누어서 하므로 저장 필요
- console.log(typeof obj);
- obj의 타입은 function 오브젝트
- bind()의 첫 번째 파라미터
- get() 함수에서 this로 참조할 오브젝트 작성
- get() 앞에 작성한 오브젝트를 this로 참조하지 않음
- 작성하지 않으면 undefined 설정
- 생성한 function 오브젝트의 [[BoundThis]]에 설정
- var result = obj();
- bind()로 생성한 function 오브젝트 호출
- book.get() 함수가 호출됨
- return this.point;
- this가 [[BoundThis]]를 참조
- 즉, book 오브젝트를 참조하므로 123 반환
파라미터 병합
var book = {
get: function(){
return Array.prototype.slice.call(arguments);
}
};
var obj = book.get.bind(this, 10, 20);
var result = obj(30, 40);
log(result);
// [10, 20, 30, 40]
- var obj = book.get.bind(this, 10, 20);
- 두 번째, 세 번째 파라미터에 값을 작성했으며
- book.get()의 파라미터 값으로 넘겨줌
- function 오브젝트의 [[BoundArguments]]에 설정
- get() 함수에 파라미터 이름을 작성하지 않고 arguments 사용
- return Array.prototype.slice.call(arguments);
- slice()는 인덱스 범위의 엘리먼트를 배열로 반환
- 인덱스를 작성하지 않으면 arguments 전체 반환
- var result = obj(30, 40);
- book.get() 함수가 호출되며
- book.get.bind(this, 10, 20);에서 10과 20을 [10, 20] 형태로 반환
- 여기에 obj(30, 40)의 30과 40을 병합(첨부)하여 반환
bind() 활용, 이벤트 처리
var book = {
myPoint: 100,
setEvent: function(){
var node = document.getElementById("point");
node.onclick = this.show.bind(book, node);
},
show: function(node, event){
log(node.textContent);
log(this.myPoint);
}
};
book.setEvent();
// 값 출력
// 100
- 시나리오
- "값 출력" 버튼을 클릭하면 값을 표시
- HTML 형태:
<script src="point.js" defer></script>
<button id=point>값 출력</button>
- 이벤트 처리의 어려움은
- 이벤트를 설정할 때의 오브젝트를 핸들러에서 this로 참조할 수 없다는 것
➡️bind()로 해결할 수 있음
- document.getElementById("point");
- button#point로 엘리먼트 오브젝트 생성
- node.onclick = this.show.bind(book, node);
- show()는 onclick 이벤트의 핸들러
- show()에서 this로 book 오브젝트를 참조하기 위해 바인드
- show() 파라미터 값으로 node를 넘겨줌
- show: function(node, event){
- button#point를 클릭했을 때 호출됨
- node: 이벤트를 설정한 엘리먼트
- event: Event 오브젝트
- console.log(this.myPoint);
- bind() 첫 번째 파라미터에 book 오브젝트를 작성했으며
- 이를 this로 참조하므로 123이 표시됨