群里有人问怎么生成一个包含调用一系列jquery对象里函数的数组,其实首选方案是数组里直接存对象,不过这个问题值得研究一下.
首先贴上一段简单的html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<html> <body> <div id="a1"></div> <div id="a2"></div> <div id="a3"></div> <div id="a4"></div> <div id="a5"></div> <div id="a6"></div> <div id="a7"></div> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script> your_codes(); </script> </body> </html> |
其中的 your_codes(); 则是接下来要说的实现代码.
一开始我的写法是这样:
1 2 3 4 5 6 |
var idfn = []; for(var i = 1; i <= 7; i = i + 1){ idfn.push(function(){ return $("#a"+i).attr("id"); }); } |
但最后生成的函数会随着 i 从栈中的消失而失去作用. 也就是说,在匿名函数内的变量 i 不能是循环里那个 i 的引用,否则最后数组里所有元素都和最后一个元素相同了.
解决方案是把 i 变成一个函数的参数,这样就新建了一个栈,隔离了各个 i 的影响:
1 2 3 4 5 6 7 8 9 |
var idfn = []; function idfn_gen(index){ return function(){ return $("#a"+index).attr("id"); }; } for(var i = 1; i <= 7; i = i + 1){ idfn.push(idfn_gen(i.toString())); } |
没错,这是一个标标准准的函数式编程,简直就是我上学期用 scheme 写的那些 assignments 的翻版. 不过 js 毕竟不是一个以函数式编程为初衷的语言,很多实现上会遇到各式各样的问题.
2014.06.08 补充:
正解:
1 2 3 4 5 6 7 8 |
var idfn = []; for(var i = 1; i <= 7; i = i + 1){ (function(i) { idfn.push(function(){ return $("#a"+i).attr("id"); }); })(i); } |
注意括号,俗称闭包
via Breezewish
这学期结束 scheme 开始上 C 的时候, professor 这样吐槽函数式编程:
“举个例子,考虑一个卖可乐的自动售货机:命令式编程(imperative programming),也就是你们学的 C ,你投下一枚硬币之后售货机内部把余额所在的内存改成了一刀,再投下一枚硬币,变成了两刀,按下可乐的按钮,余额清零了,新生成了一罐可乐;这很合理对吧,但看一下函数式编程(functional programming),比如说你们学了一学期的 Scheme ,本来是一个显示没有余额的售货机,你投下一枚硬币后,噗的一声蹦出来了一台新的售货机,余额是一刀,再投一枚又蹦出来一台新的售货机,按下可乐之后同时蹦出来一台售货机和一罐可乐. 这就是函数式编程,也是为什么函数式编程很难投入使用;不过目前随着互联网业的高速发展,这一领域被重新重视了起来.”
0 条评论。