this
자바스크립트에서 상황별로 this가 어떻게 달라지는지 알아보자.
원칙 - this는 함수를 호출할 때(실행 컨텍스트가 생성될 때) 결정된다.
- 전역 공간에서의 this
전역 공간에서 this는 전역 객체를 가리킨다. 브라우저 환경에서는 window, Node 환경에서는 global이 전역 객체이다.
- 메서드로서 호출할 때 그 메서드 내부에서의 this
어떤 함수를 호출할 때 그 함수 이름 앞에 객체가 명시돼 있는 경우에는 메서드로 호출한 것이고, 그렇지 않은 모든 경우는 함수로 호출한 것
호출한 주체에 대한 정보가 this에 담긴다. 메서드로서 호출하는 경우 this는 함수명 앞의 객체이다.
const obj = {
name: 'Alice',
greet: function() {
console.log(this);
}
};
obj.greet(); // obj
- 함수로서 호출할 때 그 함수 내부에서의 this
함수로서 호출할 경우에는 호출한 주체가 없다. 그래서 this는 전역 객체를 가리킨다.
this 바인딩에 관해서는 오직 해당 함수를 호출하는 구문 앞에 점이 있는지 없는지에 달려있다.
화살표 함수는 실행 컨텍스트를 생성할 때 this 바인딩 과정이 빠지게 되어, 상위 스코프의 this를 그대로 사용할 수 있다.
function greet() {
console.log(this);
}
greet(); // Window {...}
- 콜백 함수 호출 시 그 함수 내부에서의 this
콜백 함수에서의 this는 콜백 함수의 제어권을 가지는 코드가 콜백 함수에서의 this를 결정하며, 특별히 정의하지 않은 경우 전역객체를 가리킨다.
- 생성자 함수 내부에서의 this
생성자 함수 내부에서의 this는 곧 새로 만들 인스턴스 자신이 된다.
function Person(name) {
this.name = name;
}
const alice = new Person('Alice');
console.log(alice.name); // 'Alice'
콜백 함수
콜백 함수는 다른 코드에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수이다. 콜백 함수를 위임받은 코드는 이 콜백 함수를 적절한 시점에 실행한다.
콜백 함수로 어떤 객체의 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로써 호출된다. 이때 'this'는 전역 객체를 가리킨다.
const obj = {
name: 'gini',
func: function() {
console.log(this)
}
};
setTimeout(obj.func, 1000); // Window {...}
bind 메서드를 사용해서 콜백 함수 내부 this에 다른 값을 바인딩할 수 있다.
const obj = {
name: 'gini',
func: function() {
console.log(this)
}
};
setTimeout(obj.func.bind(obj), 1000); // {name: 'gini', func: ƒ}
클로저
클로저란 어떤 함수에서 선언한 변수를 참조하는 내부함수를 외부로 전달할 경우, 함수의 실행 컨텍스트가 종료된 후에도 해당 변수가 사라지지 않는 현상이다.
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1
counter(); // 2
클로저의 메모리 관리
클로저는 본질이 메모리를 계속 차지하는 개념이므로 더는 사용하지 않게 된 클로저에 대해서는 메모리를 차지하지 않도록 관리해줄 필요가 있다.
const outer = (function () {
let count = 0;
const inner = function() {
count++;
console.log(count);
};
return inner;
})();
outer();
outer = null;
참조하는 것을 제거하면 된다. 보통 null이나 undefined를 할당한다.
클로저 활용 사례
- 콜백 함수 내부에서 외부 데이터를 사용하고자 할 때
function fetchData(url) {
let data;
fetch(url).then(response => {
data = response.json();
console.log(data);
});
}
- 접근 권한 제어(정보 은닉)
function createCounter() {
let count = 0;
return {
increment: function() {
count++;
console.log(count);
},
decrement: function() {
count--;
console.log(count);
}
};
}
const counter = createCounter();
counter.increment(); // 1
counter.decrement(); // 0
- 부분 적용 함수
n개의 인자를 받는 함수에 미리 m개의 인자만 넘겨 기억시켰다가, 나중에 나머지 인자를 넘겨서 함수의 실행 결과를 얻을 수 있는 함수
function multiply() {
let result = 1;
for (let i = 0; i < arguments.length; i++) {
result *= arguments[i];
}
return result;
}
const multiplyPartial = multiply.bind(null, 1, 2, 3);
console.log(multiplyPartial(4, 5, 6)); // 720
- 커링 함수
여러 개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠서 순차적으로 호출될 수 있게 체인 형태로 구성한 것. 마지막 인자가 전달되기 전까지는 원본 함수가 실행되지 않는다.
function curry(func) {
return function (a) {
return function (b) {
return function (c) {
return func(a, b, c);
}
}
}
}
const curriedMax = curry(Math.max);
console.log(curriedMax(1)(2)(3)); // 3'JavaScript' 카테고리의 다른 글
| NestJS Custom Decorator로 유저 인증 처리하기 (0) | 2025.02.19 |
|---|---|
| TypeORM의 save() 사용 시 데이터 변경 감지 원리 이해하기 (0) | 2024.12.15 |
| 프로토타입 (0) | 2024.05.22 |
| 자바스크립트의 실행 컨텍스트 (0) | 2024.05.19 |
| 자바스크립트의 데이터 타입 이해 (0) | 2024.05.17 |