闭包

 1          //轮播    
 2          var slideBtns = document.getElementById("slideBtn").getElementsByTagName("li");
 3         var slideImgs = document.getElementById("slideImg").getElementsByTagName("li");
 4         var intervalId = null;
 5         var cur = 0;
 6         slideImgs[cur].style.display = "block";
 7         slideBtns[cur].style.opacity = 1;
 8          function slideFunc(){
 9                 for(var i = 0;i < 3;i++){
10                     slideImgs[i].style.display = "none";
11                     slideBtns[i].style.opacity = 0.6;
12                 }
13                 slideImgs[cur].style.display = "block";
14                 slideBtns[cur].style.opacity = 1;
15                 cur+=1;
16                 if(cur>2){
17                     cur = 0;
18                 }                
19             }    
20         
21         
22         function slideImage(){                
23             intervalId = setInterval(slideFunc,2000);    
24         }
25         slideImage(); 
26         function BtnClick(){
27             for(var j = 0;j < 3;j++){
28                 
29                 slideBtns[j].index = j;  //这里是关键
30                 slideBtns[j].onmouseover = slideBtns[j].onclick = function(){
31                     if(intervalId != null)
32                         clearInterval(intervalId);
33                     cur = this.index;
34                     slideFunc();
35                 };
36                 slideBtns[j].onmouseout = function(){
37                     cur = this.index;
38                     slideImage();
39                 };
40             }
41         }
42         BtnClick();
  • 刷牛客网的题目的时候刷到这个知识点,觉得有个回答写得很好,故摘抄之。题目:

题目描述

实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 result[i](),结果与 fn(arr[i]) 相同 
输入例子:
var arr = [1, 2, 3]; 
var square = function (x) { 
	return x * x; 
}; 
var funcs = makeClosures(arr, square); 
funcs[1]();

输出例子:
4

 

看到题目我首先想到的是使用闭包时因为作用域链引来的副作用,(闭包只能得到包含函数中变量的最后一个值)如果直接用下面第一种写法会导致result中每个函数的参数都是arr[arr.length-1],在《JavaScript高级程序设计》书中提到的最典型的解决此问题的方法就是用一个立即执行的匿名函数代替闭包负值给数组,这个匿名函数有一个参数num,因为函数参数是按值传递的所以传递给num的就是当前for循环的值。接下来的是根据其他小伙伴的解决方案进行的总结,提供给新来的小伙伴一个总结,页方便自己以后看
此外ES5提供了bind方法,apply(),call(),bind()方法在使用时如果已经对参数进行了定义
又因为在此问题中用的是数组并且需要的是arr[i]所以用forEach()方法就不用考虑第一段中提到的问题

 

 1 //这种是错误的写法会导致result中每个函数的参数都是arr[arr.length-1]
 2 function makeClosures(arr, fn) {
 3     var result = new Array();
 4      for(var i=0;i<arr.length;i++){
 5         result[i] = function(){
 6             return fn(arr[i]);            
 7         };
 8     }
 9     return result;
10 }
 1 //参考《JavaScript高级程序设计》的典型方法
 2 function makeClosures(arr, fn) {
 3     var result = new Array();
 4     for(var i=0;i<arr.length;i++){
 5         result[i] = function(num){
 6             return function(){
 7                 return fn(num);
 8                  
 9             }
10         }(arr[i]);
11     }
12     return result;
13 }
1 //使用ES5的bind()方法
2 function makeClosures(arr, fn) {
3     var result = new Array();
4     for(var i=0;i<arr.length;i++){
5         result[i] = fn.bind(null,arr[i]);
6     }
7     return result;
8 }
1 //使用forEach()
2 function makeClosures(arr, fn) {
3     var result = new Array();
4     arr.forEach(function(curr){
5         result.push(function(){return fn(curr)});
6     })
7     return result;
8 }

摘抄自https://www.nowcoder.com/questionTerminal/578026cd24e3446bbf27fe565473dc26

 

 

  • 看到一篇解释立即执行函数(IIFE)的文章,写得很好,也更加加深了我对闭包的理解,链接:

http://web.jobbole.com/82520/

 

posted @ 2017-02-18 16:00  LaddieLan  阅读(129)  评论(0编辑  收藏  举报