循环内的 JavaScript 闭包——简单实用的例子
技术问答
299 人阅读
|
0 人回复
|
2023-09-12
|
, }& S2 V4 M, E7 D# U- var funcs = ;// let's create 3 functionsfor (var i = 0; i 输出此: s3 _- k2 Z$ K8 e C: I
- My value: 3+ Y7 Q1 W* [! z$ K8 }+ F Q
- My value: 3* ~* e3 G$ L2 S0 e5 f
- My value: 3* _9 c& h+ q0 K! B' E7 K$ q$ J; P- l
而且我希望它输出:! h( F" E2 @7 \7 y
- My value: 0
) k# _& L* W7 ?5 J- My value: 1& A; k/ L! O2 _% K& f, B
- My value: 2
/ y: |9 [$ D, x/ b. x 当使用事件监听器导致函数运行延迟时,也会出现同样的问题:; f' x' A9 l5 u$ h1 J% }3 g
- [code]var buttons = document.getElementsByTagName("button");// let's create 3 functionsfor (var i = 0; i … 或异步代码,如使用 Promises:[code]// Some async wait functionconst wait = (ms) => new Promise((resolve,reject) => setTimeout(resolve,ms));for (var i = 0; i console.log(i));}0 `( _, k& d+ u- ~, t
在for in和for of循环也很明显: g- j. S) x) ?# [+ m# ]
[code]const arr = [1,2,3];const fns = [];for(var i in arr){ fns.push(() => console.log(`index: ${i}`));}for(var v of arr){ fns.push(() => console.log(`value: ${v}`));}for(var f of fns){ f()code]这个基本问题的解决方案是什么?7 J ^) m7 `0 _7 {1 d9 P
8 ]& ]. t" ~3 T, R0 v7 N1 a
解决方案: 6 S- M4 l1 N# c8 K
问题是i每个匿名函数中的变量都与函数外的相同变量绑定。
/ `6 B6 a7 W3 t% w& X4 xES解决方案: letECMAScript 6 (ES6) 引入了不同于基于变量的新关键词let和const关键字var。例如,在有let在基于索引的循环中,循环中的每个迭代都会有一个i具有循环范围的新变量,因此您的代码将按预期工作。$ p% R3 H& w2 A. a3 d* O3 G
[code]for (let i = 0; i 但请注意,Edge 14 前的 IE9-IE11 和 Edge 支持let但是会出现上述错误(他们不会i每次创建一个新的函数,所以上述所有函数都会像我们使用的 一样记录 3 var)。Edge 14 终于做到了。8 d0 O* f8 }6 Z- G' R
ES5.1 解决方案:forEach随着该Array.prototype.forEach函数的可用性相对较广(2015 年),值得注意的是,在主要涉及值数组迭代的情况下,.forEach()为每次迭代获得不同的封闭包提供了一种干净自然的方法。也就是说,假设你有一定的包含值(DOM 引用、对象等。)数组,并且设置在每个元素中,您可以这样做:% K+ ^+ g* ~- n% D( N+ r W
[code]var someArray = [ /* whatever */ ...someArray.forEach(function(arrayElement) { / ... code code code for this one element someAsynchronousFunction(arrayElement,function() arrayElement.doSomething(); );code]这个想法是和的.forEach循环回调函数的每次调用都将是其自身的封闭包。传递给处理程序的参数是特定于迭代特定步骤的数组元素。如果在异步回调中使用,则不会与迭代其他步骤中建立的任何其他回调发生冲突。
7 a% ^9 u/ N) w/ U4 J若碰巧使用 jQuery,该$.each()函数为您提供类似的功能。
: y- X9 ^6 k7 |. I" y' z经典解决方案:闭包您要做的是将每个函数中的变量绑定到函数外的一个单独的、不变的值:
) F O9 X1 A; {[code]var funcs = [];function createfunc(i) { return function() console.log("My value: " i); };}for (var i = 0; i Run code snippetHide results
' o) e. T$ a2 T. _4 d+ GFull page
+ D- p, W, s+ _; ?2 Z. n/ J由于 JavaScript 中没有块作用域-只有函数作用域-通过在新函数中创建和包装函数,您可以确保i如你所愿。 |
|
|
|
|
|