C++, JAVA와 같은 언어에서 this는 자기자신 객체를 가리킨다.
그러나 JavaScript 의 this 값은 실행 컨텍스트의 thisValue 에 의해 값이 바인딩 된다.
thisValue는 아래의 5가지 패턴에 의해 결정된다.
- 전역(global)
- 함수 호출(function Invocation)과 메서드 호출(Method Invocation)
- call(), apply(), bind()
- 생성자(Construction)
- strict 모드
💡 바인딩 : 실제 값이 변수에 묶이는 것
💡 strict 모드 : ES5 에 있는 새로운 기능으로 엄격하게 문법을 검사하는 모드이다.
1. 전역(global)
전역에서 this는 전역 컨텍스트의 영향을 받아 this 값은 전역 객체 가 된다.
// 브라우저에서는 window 가 전역객체 이다.
console.log(this === window); // true
this.myString = "hello?";
console.log(window.myString); // "hello?"
console.log(myString); // 전역 변수 myString을 출력: "hello?"
💡 NodeJS 의 경우, 전역에서의 this 값은 global 이 된다.
2. 함수 호출과 메서드 호출
함수 내부의 this 값은 함수의 호출 방식에 따라서 결정된다.
단순하게 메서드나, 내부함수, 콜백함수를 호출하는 경우 this 는 전역 객체 에 바인딩된다.
function foo() {
console.log("foo's this: ", this); // Window
function bar() {
console.log("bar's this: ", this); // Window
}
bar();
}
foo();
그러나 객체 리터럴 안에서 this는 자기 자신에게 바인딩된다.
하지만 메서드의 내부 함수는 전역 객체에 this 값이 바인딩 된다.
var value = 1;
const obj = {
value: 100,
qux: function() {
console.log(this.value); // this === obj, 100 출력
setTimeout(
// 메서드의 내부 함수
function() {
console.log(this); // this === Window, Window 출력
console.log(this.value); // 1 출력
}, 0);
}
}
obj.qux();
3. call(), apply(), bind()
call(), apply(), bind() 사용하여 this 값을 설정할 수 있다.
- call(): 이미 할당되어 있는 다른 객체의 함수/메서드를 호출하는 해당 객체에 재할당할 때 사용
- apply(): call() 과 비슷하나 인수들을 단일 배열로 받는다.
- bind(): this 값이 바인딩 된 새로운 함수를 반환한다.
var value = 20;
function mySum(num) {
// this.value 가 없는 경우
if(this.value == undefined) this.value = 50;
return this.value + num;
}
// this 값을 따로 지정하지 않아 global 객체(window)가 this가 됨
console.log(mySum(2)); // 22
// call()
console.log(mySum.call(mySum, 2)); // 52
// apply()
console.log(mySum.apply(mySum, [9])); // 59
// bind()
var bindMySum = mySum.bind(mySum);
console.log(bindMySum(50)); // 100
4. 생성자(Construction)
생성자를 사용하는 경우로new 연산자, class의 constructor를 사용하는 경우 this 바인딩이 자기 자신으로 된다.
function test(number) {
this.num = number;
}
// new 연산자를 사용하여 생성
var obj = new test(1);
console.log(obj.num); // 1
/* ================ 만약에 new 를 사용하여 obj를 선언하지 않은 경우 ================ */
// 함수내에서 this.num 은 window.num 으로 바인딩 된다.
console.log(obj.num); // Uncaught TypeError
생성자를 통해 함수를 호출하면 다음과 같은 과정으로 동작한다.
- 빈 객체 생성 및 this 바인딩
- 함수 생성전 빈 객체를 생성함(이때 this가 이 객체를 가리킴)
- 생성된 빈 객체는 생성자 함수의 prototype 을 자신의 prototype 으로 설정함
- this.메서드, this.속성 등 this를 통해 생성한 속성와 메서드는 새로 생성된 객체에 추가함
- 생성된 객체를 반환
- 반환문(return)이 없으면 암묵적으로 생성된 객체를 반환
- 반환문에 this 가 아닌 다른 객체를 반환하는 경우 해당 객체가 반환됨
function Obj(num) {
// 생성자 함수 코드 실행 전 ---------- 1
this.num= num; // ---------- 2
// 생성된 함수 반환 ------------------3
}
var me = new Obj(33);
console.log(me.num);
따라서, new 연산자를 사용하지 않고 함수로 객체를 만드는 경우
객체를 암묵적으로 생성하여 반환하지 않으며 this는 전역 객체 를 가리킨다.
📖 객체 리터럴 vs 함수
객체 리터럴 방식과 함수 방식의 차이는 [[Prototype]](프로토타입 객체) 에 있다.
> // 객체 리터럴 방식 > // [[Prototype]] : Object.prototype > var obj = { > name: "dulli", > age: 100 > } > > // 함수 방식 > // [[Prototype]] : obj.prototype > function obj2() { > this.name: "ddochi", > age: 35 > } > var objIns = new obj2(); >
5. strict 모드
strict 모드 라면 this 값은 undefined 가 된다.
// 함수 내에서 use strict 모드 활성화
function test() {
"use strict";
return this; // 여기서 this는 undefined
}
console.log(this); // Window, 전역 객체
console.log(test()); // undefined
결론
JavaScript에서는 this 값은 실행 컨텍스트의 thisValue 에 의해 값이 바인딩 된다.
thisValue 는 아래의 5가지 패턴에 의해 결정이된다.
- 전역(global) : this === 전역객체
- 함수 호출(function Invocation)과 메서드 호출(Method Invocation)
- 단순한 함수 호출 : this === 전역객체
- 객체 리터럴(메서드 호출);
- 메서드안에서 this === 자기자신
- 메서드의 내부 함수의 this === 전역객체
- call(), apply(), bind() : this 값이 매개변수에 바인딩됨
- 생성자(Construction) : this === 자기자신
- strict 모드 : this === undefined
참조
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this
https://hyunseob.github.io/2016/03/10/javascript-this/
https://muckycode.blogspot.com/2015/04/javascript-this.html
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/애로우_펑션
'📌 Front End > └ JavaScript' 카테고리의 다른 글
[JavaScript] 자바스크립트 비동기에 대해서 이해하기 (0) | 2023.03.10 |
---|---|
[JavaScript] 자바스크립트 비동기 처리 (0) | 2023.03.10 |
[JavaScript] 자바스크립트 클로저(Closure)란? (0) | 2023.03.10 |
[JavaScript] 자바스크립트 제너레이터(Generator)와 이터레이터(Iterator) (1) | 2023.03.10 |
[JavaScript] 자바스크립트 프로토타입 상속 (0) | 2023.03.10 |