UNPKG

1.82 kBMarkdownView Raw
1# Loop closures
2A loop closure that captures a block scoped loop variable can't be transpiled only with
3variable renaming.
4
5Let's take the following example:
6
7```javascript
8const arr = [];
9for (let x = 0; x < 10; x++) {
10 let y = x;
11 arr.push(function() { return y; });
12}
13```
14
15defs with default options gives you an error:
16
17 line 4: loop-variable y is captured by a loop-closure. Tried "loopClosures": "iife" in defs-config.json?
18
19This is because With ES6 semantics `y` is bound fresh per loop iteration, so each closure captures a separate
20instance of `y`, unlike if `y` would have been a `var`.
21
22You can now either choose to rewrite it manually (in usual pre-ES6 style), with an IIFE or
23bind or similar. For example:
24
25```javascript
26for (let x = 0; x < 10; x++) {
27 const arr = [];
28 (function(y) {
29 arr.push(function() { return y; });
30 })(x);
31}
32```
33
34And that runs just fine and defs stops complaining. Alternatively, you can ask defs to
35create the IIFE for you by adding `"loopClosures": "iife"` to your `defs-config.json`.
36Run on the original example, defs transpiles that without complaining to:
37
38```javascript
39var arr = [];
40for (var x = 0; x < 10; x++) {(function(){
41 var y = x;
42 arr.push(function() { return y; });
43}).call(this);}
44```
45
46Not all loop closures can be transpiled into IIFE's. If the loop body (which contains the
47loop closure) also contains a `return`, `yield`, `break`, `continue`, `arguments` or `var`, then
48defs will detect that and give you an error (because an IIFE would likely change
49the loop body semantics). If so either rewrite the loop body so it doesn't use any of these or
50insert an IIFE manually (knowing what you're doing).
51
52defs does not support transforming loops containing loop closures in any other way than
53with IIFE's, including try-catch statements.