클로저는 믿을 수 없을 만큼 간단하지만 이해하기에는 JavaScript의 매우 강력한 부분입니다. 콜백 함수가 강력한 이유, 비동기 JS와 그것이 포함하는 모든 것 (Promises 등)이 가능한 이유는 클로저입니다.
https://dev.to/ryanameri/mastering-hard-parts-of-javascript-closure-i-kg2
하지만 클로저는 무엇입니까? Dan Abramov가 가장 잘 설명합니다.
함수가 외부에서 정의 된 변수에 액세스 할 때 클로저가 있습니다.
예를 들어 이 코드 스니펫에는 클로저가 포함되어 있습니다.
let users = ["Alice", "Dan", "Jessica"];
let query = "A";
let user = users.filter((user) => user.startsWith(query));
user => user.startsWith (query) 자체가 어떻게 함수인지 주목하십시오. 쿼리 변수를 사용합니다. 그러나 쿼리 변수는 해당 함수 외부에서 정의됩니다. 그것은 closure입니다.
이것이 어떻게 가능한지? 다른 함수 내부에서 함수를 반환 할 때 함수 뿐만 아니라 "가변 환경"도 반환하기 때문입니다. 이 변수 환경에는 외부 함수에서 선언 된 모든 변수 또는 개체가 포함됩니다. 반환 된 함수는 이 외부 변수 환경에 대한 링크를 유지합니다. 이 링크는 공식적으로 '가변 환경'(C.O.V.E.)보다 Closure라고 합니다. 또는 영구 어휘 범위 참조 데이터 (P.L.S.R.D.).
개념이 약간 혼란스러울 수 있지만 이러한 연습을 함께 진행하여 마스터 할 것입니다. 항상 그렇듯이 내 솔루션을 보기 전에 먼저 문제를 해결 한 다음 비교하고 대조하는 것이 좋습니다.
연습 1
함수를 만들고 반환하는 함수 createFunction을 만듭니다. 생성 된 함수가 호출되면 "hello"를 출력해야 합니다. createFunction을 완료했다고 생각되면 코드에서 해당 줄의 주석 처리를 제거하고 실행하여 작동하는지 확인하십시오.
function createFunction() {}
const function1 = createFunction();
function1();
// => should console.log('hello');
해결책 1
function createFunction() {
function printHello() {
console.log("hello");
}
return printHello;
}
멋지고 쉬운 시작이지만 이것은 완벽한 마무리 데모입니다. 먼저 createFunction()을 호출하고 그 값을 function1에 할당합니다. function1은 이제 실제로 반환 된 것과 같이 printHello () 함수입니다. 이제 function1 ()을 호출 할 수 있으며 printHello() 함수의 본문을 실행합니다.
연습 2
하나의 입력을 받아들이고 함수를 반환하는 함수 createFunctionPrinter를 만듭니다. 생성 된 함수가 호출되면 함수 생성시 사용 된 입력을 출력해야 합니다.
function createFunctionPrinter() {}
const printSample = createFunctionPrinter("sample");
printSample();
// => should console.log('sample');
const printHello = createFunctionPrinter("hello");
printHello();
// => should console.log('hello');
해결 방법 2
function createFunctionPrinter(input) {
function printInput() {
console.log(input);
}
return printInput;
}
이전 연습과 매우 유사하지만 여기에서 COVE 또는 P.L.S.R.D의 개념도 시연하고 있습니다. 내부 함수 printInput()은 외부 함수,이 인스턴스에서는 매개 변수 입력에 있던 변수에 액세스합니다.
연습 3
외부 함수에 대한 코드를 조사하십시오. 함수를 반환하고 함수가 범위를 벗어난 변수를 사용하고 있음에 유의하십시오.
실행하기 전에 출력을 추론하십시오.
function outer() {
let counter = 0;
// this variable is outside incrementCounter's scope
function incrementCounter() {
counter++;
console.log("counter", counter);
}
return incrementCounter;
}
const willCounter = outer();
const jasCounter = outer();
willCounter();
willCounter();
willCounter();
jasCounter();
willCounter();
이제 x로 입력을 추가하는 함수를 반환하는 함수 addByX를 만듭니다.
function addByX() {}
const addByTwo = addByX(2);
console.log(addByTwo(1));
// => should return 3
console.log(addByTwo(2));
// => should return 4
console.log(addByTwo(3));
// => should return 5
const addByThree = addByX(3);
console.log(addByThree(1));
// => should return 4
console.log(addByThree(2));
// => should return 5
const addByFour = addByX(4);
console.log(addByFour(4));
// => should return 8
console.log(addByFour(5));
// => should return 9
해결책 3
function addByX(x) {
function addByNum(num) {
return num + x;
}
return addByNum;
}
우리는 이러한 유형의 기능을 이해해야 합니다. addByX가 처음 호출되면 인수를 받고 함수를 반환합니다. 이 내부 함수는 자체적으로 매개 변수를 수신하지만 자체 매개 변수와 addByX 매개 변수 모두에 액세스하므로 둘 다에 필요한 모든 계산을 수행 할 수 있습니다.
연습 4
콜백을 입력으로 받아들이고 함수를 반환하는 함수를 한 번 작성합니다. 반환 된 함수가 처음 호출 될 때 콜백을 호출하고 해당 출력을 반환해야 합니다. 추가로 호출되는 경우 콜백을 다시 호출하는 대신 처음 호출 된 출력 값을 반환합니다.
function once() {}
// /*** Uncomment these to check your work! ***/
const onceFunc = once(addByTwo);
console.log(onceFunc(4)); // => should log 6
console.log(onceFunc(10)); // => should log 6
console.log(onceFunc(9001)); // => should log 6
해결 방법 4
function once(func) {
let counter = 0;
let res = undefined;
function runOnce(num) {
if (counter === 0) {
res = func(num);
counter++;
}
return res;
}
return runOnce;
}
이것은 클로저를 사용하여 함수에 메모리를 제공하는 방법을 볼 수 있는 첫 번째 예제입니다. 외부 범위에서 카운터 변수를 선언 한 다음 내부 함수에서 변경하면 함수가 몇 번 호출되었는지 확인한 다음 내부 함수가 호출 된 횟수에 따라 다른 동작을 수행 할 수 있습니다. 이것은 우리의 기능에 훨씬 더 많은 유연성과 힘을 제공하며, 다음 연습에서 더 자세히 살펴볼 것입니다.
연습 5
그 후 첫 번째 매개 변수로 실행되고 두 번째 매개 변수로 콜백이 실행되기 전에 콜백을 호출해야 하는 횟수를 사용하여 함수를 작성합니다.
function after() {}
const called = function () {
console.log("hello");
};
const afterCalled = after(3, called);
afterCalled(); // => nothing is printed
afterCalled(); // => nothing is printed
afterCalled(); // => 'hello' is printed
해결책 5
function after(count, func) {
let counter = 0;
function runAfter() {
counter++;
if (count === counter) {
func();
}
}
return runAfter;
}
이전 연습과 유사한 예로서 여기서는 다른 동작을 보여주고 있습니다. 다시 우리는 함수가 호출 된 횟수를 결정할 수 있는 카운터를 외부 범위에 설정할 수 있음을 알 수 있습니다. 그리고 이를 바탕으로 우리는 기능에 대해 다른 로직을 구현할 수 있습니다.
등록된 댓글이 없습니다.