ES6 (ECMAScript 6)에서 변경 가능한 변수없이 x 번 반복하는 메커니즘이 있습니까?


157

xJavaScript에서 시간 을 반복하는 일반적인 방법 은 다음과 같습니다.

for (var i = 0; i < x; i++)
  doStuff(i);

그러나 ++연산자 를 사용 하거나 변경 가능한 변수를 원하지 않습니다 . ES6에는 x시간을 다른 방식 으로 반복하는 방법이 있습니까? 나는 루비의 메커니즘을 좋아한다.

x.times do |i|
  do_stuff(i)
end

JavaScript / ES6와 비슷한 것이 있습니까? 나는 속임수를 쓰고 내 자신의 발전기를 만들 수 있습니다.

function* times(x) {
  for (var i = 0; i < x; i++)
    yield i;
}

for (var i of times(5)) {
  console.log(i);
}

물론 나는 여전히을 사용하고 i++있습니다. 적어도 눈에 띄지 않습니다 :), 그러나 ES6에는 더 나은 메커니즘이 있기를 바랍니다.


3
가변 루프 제어 변수가 왜 문제가됩니까? 그냥 원리?
doldt

1
@doldt - 나는 자바 스크립트를 가르치려고 노력하고있어,하지만 난 이후까지 변경 가능한 변수의 개념을 지연 실험을하고 있습니다
에.

5
우리는 여기서 논외 주제를 얻고 있지만, 가변 변수에 대해 배우기 전에 ES6 생성기 (또는 다른 새로운 고급 개념)로
넘어가

5
@ 돌트-아마도 실험 중입니다. JavaScript에 대한 기능적 언어 접근.
.

루프에서 해당 변수를 선언하려면 let을 사용하십시오. 범위는 루프로 끝납니다.
ncmathsadist

답변:


156

확인!

아래 코드는 ES6 구문을 사용하여 작성되었지만 ES5 이하로 쉽게 작성할 수 있습니다. ES6은 "x 번 반복하는 메커니즘"을 만들 필요 는 없습니다


콜백에서 반복자가 필요하지 않은 경우 가장 간단한 구현입니다.

const times = x => f => {
  if (x > 0) {
    f()
    times (x - 1) (f)
  }
}

// use it
times (3) (() => console.log('hi'))

// or define intermediate functions for reuse
let twice = times (2)

// twice the power !
twice (() => console.log('double vision'))

반복자가 필요한 경우 카운터 매개 변수와 함께 명명 된 내부 함수를 사용하여 반복 할 수 있습니다.

const times = n => f => {
  let iter = i => {
    if (i === n) return
    f (i)
    iter (i + 1)
  }
  return iter (0)
}

times (3) (i => console.log(i, 'hi'))


더 많은 것을 배우고 싶지 않다면 여기서 읽지 마십시오 ...

그러나 그에 대해 뭔가를 느끼게해야합니다 ...

  • 단일 브랜치 if문은 추악 합니다. 다른 브랜치에서는 어떻게됩니까?
  • 함수 본문의 여러 문장 / 표현 — 절차 문제가 혼합되어 있습니까?
  • 암시 적으로 반환 undefined-불완전한 부작용의 표시

"더 나은 방법이 없습니까?"

있습니다. 먼저 초기 구현을 다시 살펴 보겠습니다

// times :: Int -> (void -> void) -> void
const times = x => f => {
  if (x > 0) {
    f()               // has to be side-effecting function
    times (x - 1) (f)
  }
}

물론 간단하지만 우리가 어떻게 전화를 걸고 f()아무 것도하지 않는 것을 주목 하십시오. 이것은 실제로 여러 번 반복 할 수있는 기능의 유형을 제한합니다. 반복자를 사용할 수 있다고해도 f(i)훨씬 다재다능하지는 않습니다.

더 나은 종류의 함수 반복 절차로 시작한다면 어떨까요? 아마도 입력과 출력을 더 잘 사용하는 것입니다.

일반 함수 반복

// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
  if (n > 0)
    return repeat (n - 1) (f) (f (x))
  else
    return x
}

// power :: Int -> Int -> Int
const power = base => exp => {
  // repeat <exp> times, <base> * <x>, starting with 1
  return repeat (exp) (x => base * x) (1)
}

console.log(power (2) (8))
// => 256

위에서 우리 repeat는 단일 함수의 반복 적용을 시작하는 데 사용되는 추가 입력을 취하는 일반 함수를 정의했습니다 .

// repeat 3 times, the function f, starting with x ...
var result = repeat (3) (f) (x)

// is the same as ...
var result = f(f(f(x)))

구현 timesrepeat

지금 이것은 쉬운 일입니다. 거의 모든 작업이 이미 완료되었습니다.

// repeat :: forall a. Int -> (a -> a) -> a -> a
const repeat = n => f => x => {
  if (n > 0)
    return repeat (n - 1) (f) (f (x))
  else
    return x
}

// times :: Int -> (Int -> Int) -> Int 
const times = n=> f=>
  repeat (n) (i => (f(i), i + 1)) (0)

// use it
times (3) (i => console.log(i, 'hi'))

함수는 i입력으로 사용하고를 반환 i + 1하기 때문에 f매번 전달하는 반복자로 효과적으로 작동합니다 .

총알 문제 목록도 수정했습니다.

  • 더 이상 못생긴 단일 지점 if진술
  • 단일 표현 체는 멋지게 분리 된 우려를 나타냅니다
  • 더 이상 쓸모없고 암시 적으로 반환되지 않음 undefined

자바 스크립트 쉼표 연산자

마지막 예제가 어떻게 작동하는지 보는 데 어려움을 겪고 있다면 JavaScript의 가장 오래된 전투 축 중 하나에 대한 인식에 달려 있습니다. 쉼표 연산자 - 짧은에, 그것은 왼쪽에서 오른쪽으로 식을 평가하고 반환 마지막 평가 식의 값을

(expr1 :: a, expr2 :: b, expr3 :: c) :: c

위의 예에서 저는

(i => (f(i), i + 1))

간결한 글쓰기 방식입니다

(i => { f(i); return i + 1 })

테일 콜 최적화

재귀 적 구현만큼 섹시하지만이 시점에서 자바 스크립트 VM이 적절한 꼬리 호출 제거를 지원할 수 있다고 생각할 수 없기 때문에 권장하는 것은 무책임 할 것입니다. "1 년 이상 지위.

repeat (1e6) (someFunc) (x)
// => RangeError: Maximum call stack size exceeded

따라서 우리는 우리의 구현을 다시 방문해야합니다 repeat 스택 안전을 하기 위해 합니다.

아래의 코드는 않습니다 가변 변수를 사용하지 않는 nx모든 돌연변이가에 국한되어 있지만, 참고 repeat어떠한 상태 변화 (돌연변이) 함수의 외부에서 볼 수 있습니다을 - 기능을

// repeat :: Int -> (a -> a) -> (a -> a)
const repeat = n => f => x =>
  {
    let m = 0, acc = x
    while (m < n)
      (m = m + 1, acc = f (acc))
    return acc
  }

// inc :: Int -> Int
const inc = x =>
  x + 1

console.log (repeat (1e8) (inc) (0))
// 100000000

이것은 "하지만 기능하지 않습니다!"라고 말하는 많은 사람들을 갖게 될 것입니다. – 알아, 진정해. 순수 표현식을 사용하여 상수 공간 반복을위한 Clojure 스타일 loop/ recur인터페이스를 구현할 수 있습니다 . 그중 아무것도 없습니다 .while

여기에서 우리는 추상적 인 while우리와 멀리 loop기능 - 그것은 특별한 찾습니다 recur루프 실행을 유지하는 유형입니다. recur유형이 아닌 경우 루프가 완료되고 계산 결과가 반환됩니다.

const recur = (...args) =>
  ({ type: recur, args })
  
const loop = f =>
  {
    let acc = f ()
    while (acc.type === recur)
      acc = f (...acc.args)
    return acc
  }

const repeat = $n => f => x =>
  loop ((n = $n, acc = x) =>
    n === 0
      ? acc
      : recur (n - 1, f (acc)))
      
const inc = x =>
  x + 1

const fibonacci = $n =>
  loop ((n = $n, a = 0, b = 1) =>
    n === 0
      ? a
      : recur (n - 1, b, a + b))
      
console.log (repeat (1e7) (inc) (0)) // 10000000
console.log (fibonacci (100))        // 354224848179262000000


24
지나치게 복잡해 보입니다 (특히 혼동됩니다 g => g(g)(x)). 내 솔루션에서와 같이 1 차 함수보다 고차 함수의 이점이 있습니까?
Pavlo

1
@naomik : 시간을내어 링크를 게시 해 주셔서 감사합니다. 매우 감사.
Pineda

1
@ AlfonsoPérez 의견을 주셔서 감사합니다. 내가 어딘가에 약간의 힌트를 줄 수 있는지 볼 것이다 ^ _ ^
감사합니다

1
@naomik 작별 TCO ! 나는 황폐하다.

10
이 답변은 많은 노력을 기울여야하기 때문에 받아 들여지고 등급이 매겨진 것처럼 보이지만 좋은 답변이라고 생각하지 않습니다. 질문에 대한 정답은 "아니오"입니다. 당신이했던 것처럼 해결 방법을 나열하는 것이 도움이되지만 그 직후에 더 좋은 방법이 있다고 말합니다. 왜 그 대답을하고 더 나쁜 것을 제거하지 않습니까? 쉼표 연산자를 설명하는 이유는 무엇입니까? 왜 클로저를 키우나요? 일반적으로 2 자 답변이있는 질문에 대한 접선이 많은 이유는 무엇입니까? 간단한 질문은 사용자가 깔끔한 프로그래밍 사실에 대한 프레젠테이션을하는 플랫폼이 아닙니다.
Timofey 'Sasha'Kondrashov

266

은 Using ES2015 확산 연산자를 :

[...Array(n)].map()

const res = [...Array(10)].map((_, i) => {
  return i * 10;
});

// as a one liner
const res = [...Array(10)].map((_, i) => i * 10);

또는 결과가 필요하지 않은 경우 :

[...Array(10)].forEach((_, i) => {
  console.log(i);
});

// as a one liner
[...Array(10)].forEach((_, i) => console.log(i));

또는 ES2015 Array.from 연산자를 사용하십시오 .

Array.from(...)

const res = Array.from(Array(10)).map((_, i) => {
  return i * 10;
});

// as a one liner
const res = Array.from(Array(10)).map((_, i) => i * 10);

반복되는 문자열이 필요한 경우 String.prototype.repeat 를 사용할 수 있습니다 .

console.log("0".repeat(10))
// 0000000000

26
더 나은 :Array.from(Array(10), (_, i) => i*10)
Bergi

6
이것이 가장 좋은 대답이어야합니다. ES6! 대단해!
Gergely Fehérvári

3
반복자 (i)가 필요하지 않은 경우 키와 값을 모두 제외하여 다음을 수행 할 수 있습니다.[...Array(10)].forEach(() => console.log('looping 10 times');
Sterling Bourne

9
그래서 당신 은 그것을 버릴 수 있도록 N 요소의 전체 배열 을 할당 합니까?
Kugel

2
Kugel의 이전 의견을 언급 한 사람이 있습니까? 나는 같은 것을 궁금해했다
Arman

37
for (let i of Array(100).keys()) {
    console.log(i)
}

이것은 작동하므로 훌륭합니다! 그러나 추가 작업이 필요하다는 점에서 조금 추악 Array합니다. 키가 사용되는 것은 아닙니다 .
.

@에서. 과연. 그러나 [0..x]JS에 대한 답변이 내 답변보다 간결하다는 것이 확실하지 않습니다 .
zerkms

이것보다 더 간결한 것이 없다는 것이 맞을 것입니다.
.

OK,이 작품의 차이점을 주어진 이유는 이해 Array.prototype.keys하고 Object.prototype.keys있지만, 그것은 확실히 첫눈에 혼동된다.
Mark Reed

1
ES2015에서 TCO를 사용하는 @cchamberlain (어디서도 구현되지 않습니까?) 덜 걱정할 수도 있지만 실제로 :-)
zerkms

29

최선의 해결책은 다음을 사용하는 것입니다 let.

for (let i=0; i<100; i++) 

그러면 i각 바디 평가에 대해 새로운 (변경 가능) 변수 가 생성되고 i다른 곳이 아닌 해당 루프 구문의 증분 식에서 만 변경됩니다.

속임수를 쓰고 제 자신의 발전기를 만들 수있었습니다. 적어도 i++시야가 맞지 않습니다 :)

충분할 것입니다. 순수한 언어로도 모든 연산 (또는 적어도 그 해석기)은 돌연변이를 사용하는 프리미티브로 만들어집니다. 범위가 올바르게 지정되어 있으면 문제가 무엇인지 알 수 없습니다.

당신은 잘해야합니다

function* times(n) {
  for (let i = 0; i < x; i++)
    yield i;
}
for (const i of times(5))
  console.log(i);

그러나 ++연산자 를 사용 하거나 변경 가능한 변수를 원하지 않습니다 .

그런 다음 유일한 선택은 재귀를 사용하는 것입니다. 가변성없이 생성기 함수를 정의 할 수도 i있습니다.

function* range(i, n) {
  if (i >= n) return;
  yield i;
  return yield* range(i+1, n);
}
times = (n) => range(0, n);

그러나 그것은 저에게 과도하게 보이고 성능 문제가있을 수 있습니다 (꼬리 제거 기능을 사용할 수 없으므로 return yield*).


1
나는이 옵션을 좋아합니다-훌륭하고 간단합니다!
DanV

2
이것은 간단하고 요점이며 위의 많은 답변과 같은 배열을 할당하지 않습니다
Kugel

@Kugel 두 번째는 스택에 할당 할 수 있습니다.
Bergi

테일 콜 최적화가 여기에서 작동하는지 잘 모르겠습니다. @Bergi
Kugel



11

답변 : 2015 년 12 월 9 일

개인적으로 나는 간결한 답변과 간결한 답변을 찾았습니다. 이 진술이 주관적 일 수 있음을 이해하므로이 답변을 읽고 동의하거나 동의하지 않는지 확인하십시오.

질문에 주어진 예는 Ruby와 같은 것입니다.

x.times do |i|
  do_stuff(i)
end

아래를 사용하여 JS에서 이것을 표현하면 허용됩니다.

times(x)(doStuff(i));

코드는 다음과 같습니다.

let times = (n) => {
  return (f) => {
    Array(n).fill().map((_, i) => f(i));
  };
};

그게 다야!

간단한 사용 예 :

let cheer = () => console.log('Hip hip hooray!');

times(3)(cheer);

//Hip hip hooray!
//Hip hip hooray!
//Hip hip hooray!

또는 허용되는 답변의 예를 따르십시오.

let doStuff = (i) => console.log(i, ' hi'),
  once = times(1),
  twice = times(2),
  thrice = times(3);

once(doStuff);
//0 ' hi'

twice(doStuff);
//0 ' hi'
//1 ' hi'

thrice(doStuff);
//0 ' hi'
//1 ' hi'
//2 ' hi'

참고-범위 기능 정의

근본적으로 매우 유사한 코드 구성을 사용하는 유사 / 관련 질문은 밑줄의 범위 함수와 비슷한 (핵심) JavaScript에 편리한 범위 함수가있을 수 있습니다.

x부터 시작하여 n 개의 숫자로 배열을 만듭니다.

밑줄

_.range(x, x + n)

ES2015

몇 가지 대안 :

Array(n).fill().map((_, i) => x + i)

Array.from(Array(n), (_, i) => x + i)

n = 10, x = 1을 사용한 데모

> Array(10).fill().map((_, i) => i + 1)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

> Array.from(Array(10), (_, i) => i + 1)
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

빠른 테스트에서 위의 각 솔루션과 doStuff 함수를 사용하여 위의 각 백만 번 실행하여 이전 접근법 (Array (n) .fill ())이 약간 더 빨랐습니다.


8
Array(100).fill().map((_,i)=> console.log(i) );

이 버전은 불변성에 대한 OP의 요구 사항을 충족시킵니다. reduce대신에 사용 을 고려하십시오map 사용 사례 따라 하십시오.

프로토 타입에서 약간의 변이를 신경 쓰지 않는 경우에도 옵션입니다.

Number.prototype.times = function(f) {
   return Array(this.valueOf()).fill().map((_,i)=>f(i));
};

이제 우리는 이것을 할 수 있습니다

((3).times(i=>console.log(i)));

추천을 +1하기 위해 +1 .fill.


IE, Opera 또는 PhantomJS에서 채우기 방법 이 지원되지 않기 때문에 투표 거부
morhook

8

또 다른 좋은 대안이 있습니다.

Array.from({ length: 3}).map(...);

주석에서 @Dave Morse가 지적한 것처럼 함수 map의 두 번째 매개 변수를 사용하여 호출을 제거 할 수도 있습니다 Array.from.

Array.from({ length: 3 }, () => (...))


2
이것이 정답입니다! 한 가지 작은 제안-이미 Array.from으로 무료로 필요한 맵과 같은 기능을 사용할 수 있습니다. Array.from({ length: label.length }, (_, i) => (...)) 이렇게하면 맵에 대한 호출을 시작하기 위해 빈 임시 배열을 만들 수 있습니다.
데이브 모스

7

내가 가르치거나 (내 코드에서 사용하는) 것이 아니지만 변수를 변경하지 않고 ES6이 필요없는 코드 골프 솔루션이 있습니다.

Array.apply(null, {length: 10}).forEach(function(_, i){
    doStuff(i);
})

유용한 답변보다 흥미로운 개념 증명이 더 많습니다.


Array.apply(null, {length: 10})그냥 아니야 Array(10)?
Pavlo

1
@Pavlo, 사실은 아닙니다. Array (10)은 길이가 10 인 배열을 만들지 만 키가 정의되어 있지 않으면이 경우 forEach 구문을 사용할 수 없습니다. 그러나 실제로 forEach를 사용하지 않으면 단순화 될 수 있습니다 (zer6을 사용하는 zerkms의 답변을 참조하십시오!).
doldt

창조적 인 @doldt,하지만 나는 가르치고 간단한 것을 찾고 있습니다.
.

5

나는 파티에 늦었지만이 질문은 검색 결과에서 자주 나타나기 때문에 길지 않은 가독성 측면에서 최고라고 생각되는 솔루션을 추가하고 싶습니다 (모든 코드베이스 IMO에 이상적임) . 그것은 변하지 만 KISS 원칙과의 균형을 잡을 것입니다.

let times = 5
while( times-- )
    console.log(times)
// logs 4, 3, 2, 1, 0

3
내가 고품격 람다 페티쉬 파티로만 설명 할 수있는 이유의 목소리가되어 주셔서 감사합니다. 나도 무해한 Google의 첫 번째 경로에 따라이 Q & A를 끝내고 여기에서 대부분의 답변으로 신속하게 내 정신을 깎았습니다. 귀하의 목록은 목록에서 첫 번째로, 간단한 문제에 대한 간단한 해결책을 고려할 것입니다.
Martin Devillers

times루프 내에서 변수 를 사용하려는 경우 약간 직관적이지 않다는 점이 문제입니다 . 아마도 countdown더 나은 이름이 될 것 입니다. 그렇지 않으면 페이지에서 가장 깨끗하고 명확한 답변입니다.
Tony Brasunas

3

Afaik, ES6에는 Ruby의 times방법 과 유사한 메커니즘이 없습니다 . 그러나 재귀를 사용하여 돌연변이를 피할 수 있습니다.

let times = (i, cb, l = i) => {
  if (i === 0) return;

  cb(l - i);
  times(i - 1, cb, l);
}

times(5, i => doStuff(i));

데모 : http://jsbin.com/koyecovano/1/edit?js,console


나는이 접근법을 좋아하고 재귀를 좋아한다. 그러나 새로운 JavaScript 사용자 루프를 표시하는 것이 더 간단한 것을 좋아합니다.
.

3

라이브러리를 기꺼이 사용하려는 경우 lodash_.times 또는 밑줄도 있습니다_.times .

_.times(x, i => {
   return doStuff(i)
})

이것은 결과의 배열을 반환하므로 실제로 다음 루비와 비슷합니다.

x.times.map { |i|
  doStuff(i)
}

2

기능 패러다임 repeat에서 보통 무한 재귀 함수입니다. 그것을 사용하려면 지연 평가 또는 연속 전달 스타일이 필요합니다.

지연 평가 기능 반복

const repeat = f => x => [x, () => repeat(f) (f(x))];
const take = n => ([x, f]) => n === 0 ? x : take(n - 1) (f());

console.log(
  take(8) (repeat(x => x * 2) (1)) // 256
);

Javascript에서 게으른 평가를 달성하기 위해 썽크 (인수가없는 함수)를 사용합니다.

연속 전달 스타일을 사용한 함수 반복

const repeat = f => x => [x, k => k(repeat(f) (f(x)))];
const take = n => ([x, k]) => n === 0 ? x : k(take(n - 1));

console.log(
  take(8) (repeat(x => x * 2) (1)) // 256
);

CPS는 처음에는 약간 무섭습니다. 그러나 항상 동일한 패턴을 따릅니다. 마지막 인수는 연속 (함수)이며 자체 본문을 호출합니다 k => k(...). CPS 밖으로 내에서 응용 프로그램을 켜지는지하시기 바랍니다 노트, 즉 take(8) (repeat...)k(take(8)) (...)경우 k부분적으로 적용됩니다 repeat.

결론

repeat종료 조건 ( )에서 반복 ( )을 분리함으로써 take우리는 유연성을 얻게됩니다.


1

이 솔루션의 장점

  • 가장 읽기 / 사용하기 (imo)
  • 반환 값을 합계로 사용하거나 무시할 수 있습니다
  • 일반 es6 버전, 코드의 TypeScript 버전 에도 연결

단점 -돌연변이. 내부에만 신경 쓰지 않고 다른 사람들도 그렇지 않을 것입니다.

예제와 코드

times(5, 3)                       // 15    (3+3+3+3+3)

times(5, (i) => Math.pow(2,i) )   // 31    (1+2+4+8+16)

times(5, '<br/>')                 // <br/><br/><br/><br/><br/>

times(3, (i, count) => {          // name[0], name[1], name[2]
    let n = 'name[' + i + ']'
    if (i < count-1)
        n += ', '
    return n
})

function times(count, callbackOrScalar) {
    let type = typeof callbackOrScalar
    let sum
    if (type === 'number') sum = 0
    else if (type === 'string') sum = ''

    for (let j = 0; j < count; j++) {
        if (type === 'function') {
            const callback = callbackOrScalar
            const result = callback(j, count)
            if (typeof result === 'number' || typeof result === 'string')
                sum = sum === undefined ? result : sum + result
        }
        else if (type === 'number' || type === 'string') {
            const scalar = callbackOrScalar
            sum = sum === undefined ? scalar : sum + scalar
        }
    }
    return sum
}

TypeScipt 버전
https://codepen.io/whitneyland/pen/aVjaaE?editors=0011


0

기능적 측면을 다루기 :

function times(n, f) {
    var _f = function (f) {
        var i;
        for (i = 0; i < n; i++) {
            f(i);
        }
    };
    return typeof f === 'function' && _f(f) || _f;
}
times(6)(function (v) {
    console.log('in parts: ' + v);
});
times(6, function (v) {
    console.log('complete: ' + v);
});

5
"기능적 측면을 다루고"그리고 가변 루프와 함께 명령형 루프를 사용합니다 i. times평범한 옛날 보다 사용하는 이유는 무엇입니까 for?
zerkms

처럼 재사용하십시오 var twice = times(2);.
Nina Scholz

그렇다면 왜 for두 번만 사용하지 않습니까?
zerkms

나는 사용하는 것을 두려워하지 않습니다. 문제는 variabele을 사용하지 않는 것이 었습니다. 그러나 결과는 항상 일종의 캐싱 일명 변수입니다.
Nina Scholz

1
"variabele을 사용하지 않는 것이 었습니다"--- 당신은 여전히 ​​그것을 사용합니다- i++. 함수에서 받아 들일 수없는 것을 감싸는 것이 어떻게 더 나은지 분명하지 않습니다.
zerkms

0

발전기? 재귀? 왜 돌연변이에 대해 너무 싫어합니까? ;-)

"숨기기"만 허용된다면 단항 연산자의 사용을 수락하면 일을 단순하게 유지할 수 있습니다 .

Number.prototype.times = function(f) { let n=0 ; while(this.valueOf() > n) f(n++) }

루비처럼 :

> (3).times(console.log)
0
1
2

2
엄지 손가락 : "왜 뮤 타틴을 싫어하니?"
Sarreph

1
몽키 패치에서는 루비 스타일로 전환하기 위해 간단하게 엄지 손가락을 씁니다. 그 나쁜 나쁜 원숭이들에게 거부하십시오.
mrm

1
@mrm은 이것이 "원숭이 패치"입니다. 이것이 단순한 확장 사례가 아닌가? 포용 및 확장 :)
conny

아니요. Number (또는 String 또는 Array 또는 사용자가 작성하지 않은 다른 클래스)에 함수를 추가하는 것은 정의에 따라 polyfill 또는 monkey patch이며 심지어 polyfill도 권장하지 않습니다. "monkey patch", "polyfill"및 권장되는 대안 인 "ponyfill"의 정의를 읽으십시오. 그것이 당신이 원하는 것입니다.
mrm 2016 년

Number를 확장하려면 다음을 수행하십시오. class SuperNumber extends Number {times (fn) {for (let i = 0; i <this; i ++) {fn (i); }}}
Alexander

0

@Tieme의 답변을 도우미 함수로 감쌌습니다.

TypeScript에서 :

export const mapN = <T = any[]>(count: number, fn: (...args: any[]) => T): T[] => [...Array(count)].map((_, i) => fn())

이제 다음을 실행할 수 있습니다.

const arr: string[] = mapN(3, () => 'something')
// returns ['something', 'something', 'something']

0

내가 이걸 만들었 어:

function repeat(func, times) {
    for (var i=0; i<times; i++) {
        func(i);
    }
}

용법:

repeat(function(i) {
    console.log("Hello, World! - "+i);
}, 5)

/*
Returns:
Hello, World! - 0
Hello, World! - 1
Hello, World! - 2
Hello, World! - 3
Hello, World! - 4
*/

i변수는 반복 된 횟수를 반환합니다. x 크기의 이미지를 미리로드해야하는 경우에 유용합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.