2012-09-07 3 views
1

가능한 중복 :
Javascript closure inside loops - simple practical example자바 스크립트 원치 않는 폐쇄 동작

나는이 비슷한 코드를하려고했다 : funcs[0]를 호출, 분명히

var funcs = []; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=function() { 
     alert(i); 
    }; 
} 

을 경고하지 않습니다 0을 예상대로 사용하면 변수 i은 익명의 함수에 의해 캡처되고 funcs[0..4] 중 하나를 호출하면 '4'가 표시됩니다 (마지막 반복 후 i의 값이며 모든 생성 된 함수에서 공유 됨).

var funcs = []; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=(function(cap) { 
     return function() {alert(cap)}; 
    })(i); 
} 

이 트릭을 할,하지만 정말 수수께끼 읽기 어려운 것 같다

그 주위 첫 번째 작업은 함수 발생기의 어떤 종류를 사용하고 내 마음에 온다. 함수 래퍼를 사용하지 않고 의도 한 동작을 얻는 더 좋은 방법이 있습니까?

+0

function 문 다음에'funcs [i] .i = i;'를 사용할 수 없습니까? –

+1

(Chrome 21/Mac 10.7) http://jsfiddle.net/VDm5C/ –

+0

Nop, 내가 실제로 작업하고 있기 때문에 범위가 'funcs [i]'함수를 호출 할 때 설정되기 때문에 . 콜 (someObject, ..)'. 이것은'this'를 오버라이드 할 것이고'this.i'는 접근 할 수 없을 것입니다. – sitifensys

답변

2

.bind 기능을 사용하면 바인딩 기능에 추가 매개 변수를 바인드를 미리 할 수 ​​있습니다 : 그것은 더 읽기 더 LOC하지만 때로는

var funcs = []; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=function(i) { 
     alert(i); 
    }.bind(this, i); 
} 

이는 ES5 기능, 그래서 임해야 IE9 +, Chrome, Safari, Firefox :

+1

IE는 여전히 실제 브라우저가 아닙니다. p (그냥 트롤링) – sitifensys

0

코드를 익명 함수와 함께 포함하지 않으려는 경우 상태 (i)와 함수 (프로토 타입)를 모두 포함하는 클래스를 정의 (이름 지정)하는 것이 솔루션입니다.

var funcs = []; 
function MyFunc(i) { 
    this.i=i; 
} 
MyFunc.prototype.doIt = function(){ 
    alert(this.i); 
}; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=new MyFunc(i); 
} 

funcs[2].doIt();​ 
2

가능한 한 간단하게 작성해야합니다. 이해하기 쉽지만 읽는 것이 어렵다고 생각합니다. 그래서 그것을 단순화하는 한 가지 방법은 중첩 된 코딩 스타일을 사용하는 것입니다. 나는 그것이 지금처럼 단순 할 수 없다고 생각하지 않는다.

나는이 방법을 건의 할 것입니다 :

var funcs = []; 

for (var i = 0; i < 5; ++i) { 
    funcs[i] = (
     function (cap) { 
      return function() { alert(cap) }; 
     } 
    )(i); 
} 
1

이럴라는 기능은 성능과 가독성을 이유로 종종 우수하다. 왜 이런 식으로하지 :

function foo (cap) { 
    return function() { alert(cap) }; 
} 

var funcs = []; 
for (var i=0; i<5 ; ++i) { 
    funcs[i]=foo(i); 
} 
+0

다른 곳에서 사용되지 않는 최상위 기능을 작성해야하기 때문에? – Jon

+2

Jon : 최상위 수준 일 필요는 없으며 범위에 있어야합니다. –

+0

물론, 내 부분에 잘못된 표현; 거기있는 척 하지마. 여전히 이상적은 아니지만 실제로는 예를 들어와 같은 바람직하지 않은 기술입니다. C++ 및 C#과 같은 언어로 클로저를 시뮬레이트하는 클래스를 생성합니다. 둘 다 특별히 람다를 추가 했으므로 이러한 종류의 "기계류"코드를 작성할 필요가 없습니다. – Jon

0

이 시도 :

var funcs = [0, 1, 2, 3, 4].map(function(i) { 
    return function() {alert(i);}; 
}); 

참고 : map은 IE8 이상에 의해 국내외 무선하지만, 그것을 위해 common polyfill있다되지 않습니다.

+0

나는 거의 이와 같은 답을 썼지 만'[0, 1, 2, 3, 4, ...]'는 비례하지 않는다고 결정했다 ... – Alnitak

+0

@Alnitak 나는 그 느낌을 안다. 나는 단지 다른 것을 보여주고 싶었다. 이것은 모두 일부 배열 생성 알고리즘에 속합니다. 어쩌면 문자열을 분할하거나,'Uint8Array'를 만들거나 뭐든지간에 ... – MaxArt

+0

아, 지금은 _ __ 해결할 수 있습니다 : Array.range = function f (m, n, z) {return m <= - n? (z = f (m, n), z.push (n), z) : []}; – Alnitak

관련 문제