연습 16
인수를 허용하지 않는 함수 평균을 만들고 함수를 반환합니다 (단독 인수로 숫자를 받거나 인수가 아예 허용되지 않음). 반환 된 함수가 숫자로 호출 될 때 출력은 해당 함수로 전달 된 모든 숫자의 평균이어야 합니다 (중복 숫자는 다른 숫자와 마찬가지로 계산 됨). 반환 된 함수가 인수 없이 호출되면 현재 평균이 출력 됩니다. 반환 된 함수가 숫자가 전달되기 전에 인수 없이 호출되면 0을 반환해야 합니다.
function average() {}
const avgSoFar = average();
console.log(avgSoFar()); // => should log 0
console.log(avgSoFar(4)); // => should log 4
console.log(avgSoFar(8)); // => should log 6
console.log(avgSoFar()); // => should log 6
console.log(avgSoFar(12)); // => should log 8
console.log(avgSoFar()); // => should log 8
솔루션 16
function average() {
let counter = 0;
let total = 0;
function closureFn(num) {
if (num === undefined) {
return counter === 0 ? 0 : total / counter;
}
counter++;
total += num;
return total / counter;
}
return closureFn;
}
다시 예제 출력은 필수 기능을 명확하게 해야 합니다. 평균을 생성하고 있으므로 외부 범위에 두 개의 변수, 개수를 유지하는 카운터와 총 전달 된 인수의 합계를 추적하는 변수가 필요합니다. 내부 함수는 인수 수신 여부에 따라 다른 기능을 보여줍니다.
연습 17
배열 (요소가 두 개인 하위 배열)을 허용하고 함수 (콜백을 허용)를 반환하는 함수 makeFuncTester를 만듭니다. 콜백으로 전달되는 첫 번째 요소 (각 하위 배열의)가 모두 해당하는 두 번째 요소 (동일한 하위 배열의)를 생성하면 반환 된 함수는 true를 반환해야 합니다. 그렇지 않으면 반환 된 함수가 false를 반환해야 합니다.
function makeFuncTester() {}
const capLastTestCases = [];
capLastTestCases.push(["hello", "hellO"]);
capLastTestCases.push(["goodbye", "goodbyE"]);
capLastTestCases.push(["howdy", "howdY"]);
const shouldCapitalizeLast = makeFuncTester(capLastTestCases);
const capLastAttempt1 = (str) => str.toUpperCase();
const capLastAttempt2 = (str) => str.slice(0, -1) + str.slice(-1).toUpperCase();
console.log(shouldCapitalizeLast(capLastAttempt1));
// => should log false
console.log(shouldCapitalizeLast(capLastAttempt2));
// => should log true
솔루션 17
function makeFuncTester(arrOfTests) {
function closureFn(callback) {
return arrOfTests.every((couple) => callback(couple[0]) === couple[1]);
}
return closureFn;
}
클로저와 콜백을 혼합하고 있으므로 여기서는 약간 혼란스러울 수 있지만 기본적으로 배열 (배열)을 외부 함수에 전달한 다음 콜백을 내부 함수에 대한 인수로 제공 할 때 확인해야 합니다. 콜백의 결과가 원래 배열의 두 번째 요소로 올바르게 저장됩니다.
여기서 Array.prototype.every() 메서드를 사용하는 것에 주목하십시오. 콜백이 배열의 모든 요소에 대해 true를 반환하는 경우에만 true를 반환하는 매우 유용한 Array 메서드입니다. 코드를 상당히 단순화합니다.
연습 18
숫자 (제한으로 사용됨)를 허용하고 함수 (문자열을 허용 함)를 반환하는 함수 makeHistory를 만듭니다. 반환 된 함수는 반환 된 함수에 전달 된 가장 최근 "제한"문자열 수의 기록을 저장합니다 (호출 당 하나만). 문자열이 함수에 전달 될 때마다 함수는 그 뒤에 'done'이라는 단어가 있는 동일한 문자열을 반환해야 합니다 (공백으로 구분). 그러나 문자열 'undo'가 함수에 전달되면 함수는 히스토리에 저장된 마지막 작업을 삭제하고 삭제 된 문자열을 공백으로 구분 한 뒤에 '실행 취소'라는 단어와 함께 반환해야 합니다. '실행 취소'가 함수에 전달되고 함수의 히스토리가 비어있는 경우 함수는 '실행 취소 할 없음'문자열을 반환해야 합니다.
function makeHistory() {}
const myActions = makeHistory(2);
console.log(myActions("jump"));
// => should log 'jump done'
console.log(myActions("undo"));
// => should log 'jump undone'
console.log(myActions("walk"));
// => should log 'walk done'
console.log(myActions("code"));
// => should log 'code done'
console.log(myActions("pose"));
// => should log 'pose done'
console.log(myActions("undo"));
// => should log 'pose undone'
console.log(myActions("undo"));
// => should log 'code undone'
console.log(myActions("undo"));
// => should log 'nothing to undo'
해결책 18
function makeHistory(limit) {
const memory = [];
function closureFn(input) {
if (input !== "undo") {
if (memory.length >= limit) memory.shift();
memory.push(input);
return input + " done";
} else {
if (memory.length === 0) return "nothing to do";
let remove = memory.pop();
return remove + " undone";
}
}
return closureFn;
}
"실행 취소"를 구현하는 것은 흥미로운 도전이었습니다. 우리는 기본적으로 외부 스코프 (이번에는 배열의 형태로)의 일반적인 메모리가 필요하지만 메모리는 제한 항목 만 늘려야 합니다. 따라서 우리는 메모리 배열에 얼마나 많은 항목이 있는지 계산해야 하며, 더 많은 요소를 입력하면 FIFO 방식으로 슬라이딩 창을 구현하여 정확한 항목 수만 유지해야 합니다.
연습 19
이러한 지침을 이해하는 데 도움이 필요한 경우 주석 처리 된 테스트 사례를 주의 깊게 검사하십시오.
배열 (1부터 11까지의 숫자 포함)을 받아들이고 DEALER 함수를 반환하는 함수 블랙 잭을 만듭니다. DEALER 함수는 두 개의 인수 (두 숫자)를 취한 다음 PLAYER 함수를 호출하는 ANOTHER 함수를 반환합니다. PLAYER 함수를 처음 호출하면 DEALER 함수에 전달 된 두 숫자의 합계를 반환합니다.
PLAYER 함수의 SECOND 호출시 다음 중 하나를 반환합니다.
블랙 잭으로 전달 된 배열의 첫 번째 숫자와 DEALER 함수에 인수로 전달 된 두 숫자의 합계, 합계가 21 이하인 경우 또는 합계가 21을 초과하면 문자열 'bust'.
'bust'인 경우 PLAYER 함수를 호출 할 때마다 'you are done!'문자열이 반환 됩니다. (그러나 'bust'와 달리 'you are done!'출력은 배열의 숫자를 사용하지 않습니다.) 'bust'가 아닌 경우 다음 PLAYER 함수 호출은 다음 중 하나를 반환합니다.
새 합계가 21 이하인 경우 가장 최근 합계와 배열의 다음 숫자 (새 합계), 또는 새 합계가 21을 초과하는 경우 문자열 'bust'.
다시 말하지만 'bust'이면 PLAYER 함수의 모든 후속 호출은 'you are done!'문자열을 반환합니다. 그렇지 않으면 배열의 다음 숫자와 함께 다음 합계를 계속 제공 할 수 있습니다. 주어진 배열이 숫자가 떨어지기 전에 '버스트'를 줄만큼 충분히 길다고 가정 할 수 있습니다.
보너스 : DEALER 함수가 더 많은 PLAYER 함수를 반환 할 수 있도록 블랙 잭을 구현하여 이전 PLAYER 함수가 중단 된 후에도 배열에서 다음 숫자를 계속 가져옵니다. 배열에 모든 PLAYER 기능을 위한 충분한 숫자가 있는지 확인하기 만하면 됩니다.
function blackjack() {}
// /*** DEALER ***/
const deal = blackjack([
2,
6,
1,
7,
11,
4,
6,
3,
9,
8,
9,
3,
10,
4,
5,
3,
7,
4,
9,
6,
10,
11,
]);
// /*** PLAYER 1 ***/
const i_like_to_live_dangerously = deal(4, 5);
console.log(i_like_to_live_dangerously());
// => should log 9
console.log(i_like_to_live_dangerously());
// => should log 11
console.log(i_like_to_live_dangerously());
// => should log 17
console.log(i_like_to_live_dangerously());
// => should log 18
console.log(i_like_to_live_dangerously());
// => should log 'bust'
console.log(i_like_to_live_dangerously());
// => should log 'you are done!'
console.log(i_like_to_live_dangerously());
// => should log 'you are done!'
// /*** BELOW LINES ARE FOR THE BONUS ***/
// /*** PLAYER 2 ***/
const i_TOO_like_to_live_dangerously = deal(2, 2);
console.log(i_TOO_like_to_live_dangerously());
// => should log 4
console.log(i_TOO_like_to_live_dangerously());
// => should log 15
console.log(i_TOO_like_to_live_dangerously());
// => should log 19
console.log(i_TOO_like_to_live_dangerously());
// => should log 'bust'
console.log(i_TOO_like_to_live_dangerously());
// => should log 'you are done!
console.log(i_TOO_like_to_live_dangerously());
// => should log 'you are done!
// /*** PLAYER 3 ***/
const i_ALSO_like_to_live_dangerously = deal(3, 7);
console.log(i_ALSO_like_to_live_dangerously());
// => should log 10
console.log(i_ALSO_like_to_live_dangerously());
// => should log 13
console.log(i_ALSO_like_to_live_dangerously());
// => should log 'bust'
console.log(i_ALSO_like_to_live_dangerously());
// => should log 'you are done!
console.log(i_ALSO_like_to_live_dangerously());
// => should log 'you are done!
해결책 19
function blackjack(array) {
let dealerCount = 0;
function dealer(a, b) {
let playerCount = 0;
let total = a + b;
function player() {
if (total === "bust") return "you are done!";
dealerCount++;
playerCount++;
if (playerCount === 1) return total;
total += array[dealerCount - 2];
if (total > 21) {
total = "bust";
dealerCount--;
}
return total;
}
return player;
}
return dealer;
}
이 시점에서 코드는 매우 자명해야 하므로 한 줄씩 설명하지는 않겠습니다. 여기서 가장 중요한 개념은 여기에 두 개의 클로저가 있다는 것입니다. 외부 기능은 카드 덱, 딜러로 생각할 수있는 내부 기능, 플레이어로 생각할 수 있는 내부 기능으로 생각할 수 있습니다. 블랙 잭에 대해 논리적으로 생각하면 딜러는 많은 플레이어를 거래 할 수 있으며 단일 카드 덱을 여러 거래에 사용할 수 있습니다. 이렇게 생각하면 메모리 역할을 하는 각 변수가 어디에 있어야 하는지 명확히 해야 합니다.
보너스 부분을 구현하려면 딜러와 플레이어를 위한 두 개의 다른 카운터가 필요하다는 사실을 깨닫고 올바르게 계산하기 위해 로직을 아주 약간 수정해야 했습니다.
나는 내가 이 시간과 시간을 반복했다는 것을 알고 있지만, 나는 일반적으로 OOP 패러다임을 사용하여 다른 언어로 꽤 여러 번 블랙 잭 연습을 구현했다. 항상 이것보다 더 많은 코드가 필요했습니다. 클로저를 사용하고 메모리가 기능을 제공하는 힘을 깨닫는 것은 매우 놀랍습니다.
closure 연습을 마쳤습니다. 다음 단계 : 비동기 JavaScript!
등록된 댓글이 없습니다.