Typescript的Lambda表达式和闭包(作用域)

4

我要为多个用户加载一些数据,并将其存储到JavaScript数组中。 在纯TypeScript中,我会像这样写:

for(var i = 0; i < 5; i++) {
   promise[i] = httpquery.then( 
     (data) => { this.usersData[i] = data }
   );
)

...

this.$q.all[promise].then(......

很遗憾,我的TypeScript Lambda只保护了这个(而不是变量i)。因此,在我的情况下,它将始终将数据存储在this.usersData[5]中。

没错,我需要一个闭包,而我理解的TypeScript的部分语言是Lambda表达式与闭包有些相似。

所以让我们尝试在TypeScript中做些什么:

for(var i = 0; i < 5; i++) {
   promise[i] = (index = i) => {
       return httpquery.then( 
          (data) => { this.usersData[index] = data }
       );
   }();
)

这段代码完全不起作用(甚至无法编译)。为什么?因为似乎() => {}并不是真正的函数。我通过以下方式解决了这个问题:

for(var i = 0; i < 5; i++) {
   var getData = (index = i) => {
       return httpquery.then( 
          (data) => { this.usersData[index] = data }
       );
   };
   promise[i] = getData();
)

我发现这并不是非常美观 :-p。所以我的问题是:在这种情况下该如何处理?像我一样吗?还是有一种更美观的使用 TypeScript 中 Lambda 的方法?为什么呢?

 () => {}() 

不起作用但是

 var test = () => {}; 
 test(); 

这是由于typescript编译器不够智能,无法理解lambda表达式是一个函数导致的吗?

谢谢。

1个回答

3
原因是:
promise[i] = (index = i) => {
  return httpquery.then( 
    (data) => { this.usersData[index] = data }
  );
}();

因为它不是有效的JavaScript(var x = a => { return a + 1; }(3)在JavaScript和TypeScript中都是一个SyntaxError),所以它不能进行解析。只需将lambda用括号括起来即可使其成为有效表达式。
但是,仅仅这样做并不能解决您的捕获问题-默认参数在每次调用时都会被评估,因此它们都会指向var的最终绑定值。
相反,您可以选择以下两种方式之一:
A) 在初始化器中使用let(在这种情况下,TypeScript将自动执行正确操作:
for(let i = 0; i < 5; i++) {
  promise[i] = httpquery.then(data => this.usersData[i] = data);
}

B) 手动创建闭包:

for(var i = 0; i < 5; i++) {
  promise[i] = (index => httpquery.then(data => this.usersData[index] = data))(i);
}

确实,使用let是最美丽的解决方案。我仍然使用var,并没有花时间去看let/const,我认为现在是改变这个坏习惯的时候了。 谢谢! - Adavo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接