댓글 검색 목록

[javascript] JavaScript의 어려운 부분 마스터하기 : Closure III

페이지 정보

작성자 운영자 작성일 20-09-05 14:53 조회 608 댓글 0

연습 11 


함수를 받고 함수를 반환하는 함수 dateStamp를 만듭니다. 반환 된 함수는 전달 된 함수가 허용하는 많은 인수를 허용하고 호출 시간이 있는 타임 스탬프가 포함 된 날짜 키와 전달 된 함수 호출의 결과를 포함하는 출력 키가 있는 객체를 반환합니다. 힌트 : Date 객체에 대한 정보에 액세스하는 방법을 조사해야 할 수도 있습니다. 


https://dev.to/ryanameri/mastering-hard-parts-of-javascript-closure-iii-56m3


function dateStamp() {}
const stampedMultBy2 = dateStamp((n) => n * 2);
console.log(stampedMultBy2(4));
// => should log { date: (today's date), output: 8 }
console.log(stampedMultBy2(6));
// => should log { date: (today's date), output: 12 }



솔루션 11 


function dateStamp(func) {
  const logTime = {};
  function stamping(input) {
    logTime.date = new Date();
    logTime.output = func(input);
    return logTime;
  }
  return stamping;
}


함수 메모리를 제공하는 또 다른 방법은 여기에서 함수가 호출 된 횟수를 세는 대신에 함수가 호출 된 시기를 추적하는 것입니다. 우리 함수는 메모리가 필요하기 때문에 외부 범위, 즉 클로저에 영구 객체가 있어야 합니다. 그런 다음이 객체는 함수가 호출 될 때로 설정된 날짜 속성과 두 번째 함수의 매개 변수를 인수로 사용하여 원래 매개 변수의 반환 값으로 설정된 출력 속성을 가져옵니다.


우리는 지금 우리의 함수에 메모리를 부여하는 것에 대해 꽤 확신을 가질 것입니다. 이것이 기본적으로 클로저의 요점입니다.


연습 12 


인수를 받지 않는 함수 검열을 만듭니다. 검열은 두 개의 문자열 또는 하나의 문자열을 받아들이는 함수를 반환합니다. 두 개의 문자열이 주어지면 반환 된 함수는 나중에 사용하기 위해 두 문자열을 한 쌍으로 유지합니다. 하나의 문자열이 주어지면 반환 된 함수는 동일한 문자열을 반환합니다. 단, 첫 번째 문자열 (저장된 쌍)의 모든 인스턴스는 해당하는 두 번째 문자열 (저장된 쌍)로 대체됩니다. 


function censor() {}
const changeScene = censor();
changeScene("dogs", "cats");
changeScene("quick", "slow");
console.log(changeScene("The quick, brown fox jumps over the lazy dogs."));
// => should log 'The slow, brown fox jumps over the lazy cats.'



솔루션 12 


function censor() {
  const phrases = new Map();
  function actualFn(...args) {
    if (args.length === 2) {
      phrases.set(args[0], args[1]);
    } else {
      let input = args[0];
      for (let [key, value] of phrases) {
        let regex = new RegExp(key, "g");
        input = input.replace(regex, value);
      }
      return input;
    }
  }
  return actualFn;
}


이제 우리의 기능이 조금 더 흥미로워지고 있습니다. 하지만 이 연습을 세분화해도 이전 연습에서 연습했던 것과 동일한 작업을 수행하는 것입니다. 즉, 일종의 기억이 필요합니다. 함수는 전달 된 인수의 수에 따라 다른 동작을 가져야 합니다.


이 연습에서는 메모리 부분에 Map()을 사용하기로 결정했지만 객체도 사용할 수 있습니다. 나머지 매개 변수를 사용하여 내부 함수에 전달 된 모든 인수를 캡처 한 다음 배열의 크기를 확인하여 얼마나 많은 인수가 있는지 확인합니다. 

두 개의 인수가 전달되면 구문 맵에 저장하고 완료됩니다. 인수가 하나만 전달 된 경우 string.prototype.replace()를 사용하고 구문 맵에 이전에 저장된 값과 일치하는 문자열의 모든 항목을 바꿉니다.


새로운 String.prototype.replaceAll()을 사용하고 싶었지만 이 글을 쓰는 시점에서는 아직 널리 지원되지 않습니다 (예를 들어 연습을 실행하는 데 사용하는 node.js 14 버전에서는 지원되지 않습니다). replaceAll()에 대한 지원이 더 널리 보급되면 이를 사용할 수 있으며 정규식을 구성 할 필요가 없습니다.


연습 13 


JavaScript 객체에는 개인 속성과 같은 것이 없습니다! 그러나 아마도 있습니까? 모든 값을 비밀로 받아들이고 두 개의 메서드 만 있는 객체를 반환하는 함수 createSecretHolder(secret)를 구현합니다. 

비밀을 설정하는 비밀 setSecret()를 반환하는 getSecret() 


function createSecretHolder() {}
const obj = createSecretHolder(5);
console.log(obj.getSecret());
// => returns 5
obj.setSecret(2);
console.log(obj.getSecret());
// => returns 2


솔루션 13 


function createSecretHolder(secret) {
  let num = secret;
  const obj = {
    getSecret() {
      return num;
    },
    setSecret(n) {
      num = n;
    },
  };
  return obj;
}


하아! getter 및 setter를 구현하는 흥미로운 방법! 4 장, 클래스와 프로토 타입에서 더 자세히 다룰 것이지만, 여기서는 JS의 클래스가 (대부분) 구문 적 설탕이기 때문에 이러한 게터와 세터가 어떻게 이면에서 구현 될 수 있는지 살펴 보겠습니다.


또한 이제 ES2019에 추가 된 개인 클래스 필드의 형태로 JS의 개체에 개인 속성을 설정할 수 있다고 생각합니다 (이 두 단락이 이해가 되지 않더라도 걱정하지 마세요. 여전히 운동을 해결할 수 있어야 합니다!)


그래서 이것을 어떻게 해결 했습니까? 함수를 반환하는 대신 여기에서 객체를 반환했습니다. 그러나 우리의 객체에는 두 가지 메소드가 있습니다. 하나는 매개 변수를 받지 않고 대신 외부 범위에 저장된 num 변수의 값을 반환하는 getter입니다. 다른 하나는 그 값을 변경하는 setter입니다. 객체는 지속적이고 값을 유지하기 때문에 Java와 같은 OOP 언어에서 일반 getter 및 setter가 작동하는 방식과 유사하게 작동합니다.


연습 14 


새 함수를 반환하는 함수 callTimes를 작성합니다. 새 함수는 호출 된 횟수를 반환해야 합니다. 


function callTimes() {}
let myNewFunc1 = callTimes();
let myNewFunc2 = callTimes();
console.log(myNewFunc1()); // => 1
console.log(myNewFunc1()); // => 2
console.log(myNewFunc2()); // => 1
console.log(myNewFunc2()); // => 2


솔루션 14 


function callTimes() {
  let counter = 0;
  function insideFn() {
    counter++;
    return counter;
  }
  return insideFn;
}


최근의 몇 가지 연습과 비교하면 이것은 다소 간단하지만 함수가 호출 된 횟수를 계산하는 방법을 기억하는 것이 좋습니다. COVE (외부 변수)에 액세스 할 수 있고 둘 다 검색하거나 변경할 수 있다는 좋은 데모입니다.


연습 15 


숫자를 받아들이고 (n이라고 부르겠습니다) 함수를 반환하는 함수 russianRoulette를 만듭니다. 반환 된 함수는 인수를 취하지 않으며 처음 n-1 번 호출 될 때 문자열 'click'을 반환합니다. 바로 다음 호출 (n 번째 호출)에서 반환 된 함수는 문자열 'bang'을 반환합니다. 그 이후의 모든 호출에서 반환 된 함수는 '다시 재생하려면 다시 로드 '문자열을 반환합니다. 


function russianRoulette() {}
const play = russianRoulette(3);
console.log(play());
// => should log 'click'
console.log(play());
// => should log 'click'
console.log(play());
// => should log 'bang'
console.log(play());
// => should log 'reload to play again'
console.log(play());
// => should log 'reload to play again'


해결책 15 


function russianRoulette(num) {
  let count = 0;
  function closureFn() {
    count++;
    if (count < num) return "click";
    else if (count === num) return "bang";
    else return "reload to play again";
  }
  return closureFn;
}


러시안 룰렛은 무섭게 들리지만 이것은 지난 몇 번의 연습에서 해결했던 것과 동일한 문제의 변형입니다. 함수가 호출 된 횟수를 세고 그에 따라 다른 작업을 수행합니다. 여기서 우리가 하는 일은 원래 함수 (숫자)에 전달 된 매개 변수에 따라 달라집니다.


closure의 유연성과 힘은 여기에서 매우 분명해야 합니다. Java와 같은 전통적인 OOP 언어를 사용하여 이 기능을 구현하려면 훨씬 더 많은 코드 라인이 필요합니다.



댓글목록 0

등록된 댓글이 없습니다.

웹학교 로고

온라인 코딩학교

코리아뉴스 2001 - , All right reserved.