个人对闭包的一些理解 逃离我推掉我的手 2022-06-15 04:21 189阅读 0赞 ## 闭包 : 讲得通俗一点,闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数 ## ### 跳过闭包的创建过程直接理解闭包的定义是非常困难的,我们先看下面这段代码 ### function outer(){ var a = 0; return function(){ a++; alert(a); } } var f = outer(); //f接收返回值 匿名函数; f(); // a : 1; f(); // a : 2; #### 正如上面定义所说的,outer里面的匿名函数有权限访问outer函数内的变量,并可以返回给我们; #### ### 闭包一般要解决的问题 ### #### 在函数外面操作函数里面的变量(数据); #### function outer (){ var num = 0; function inner (value){ return value ? num = value : num; } return inner; } outer()(1000); // num: 1000 outer()(); // num: 0 #### 利用outer函数的返回的函数操作outer函数里的变量; #### ### 闭包不止可以返回函数,还可以通过返回对象的形式访问变量; ### function outer(){ var num = 100; var num1 = 1000; return { setNum: function (value){ num = value; }, getNum : function (){ return num; }, setNum1 : function(value){ num = value }, getNum1: function(){ return num; } } } var obj = outer(); obj.setNum(10000); console.log(obj.getNum()); obj.setNum(1); console.log(obj.getNum()); ### 关于闭包中,外部函数被调用多次的情况 ### function outer(){ var num = Math.random(); function inner(){ return num; } return inner; } // 第一种情况,外部函数被调用一次 var f = outer(); console.log(f()); //结果相同 console.log(f()); //结果相同 // 第二种情况,外部函数被调用多次 console.log(outer()()); // 不同 console.log(outer()()); // 不同 #### 如果外部函数被调用多次,就相当于开辟了多个作用域,每个作用域中都有一个num,所以值肯定不同 #### ### 闭包的用途 ### #### 1. 可以保护变量,给变量的赋值提供专有的渠道,在这个专有的渠道中,可以设置一些校验的逻辑!可以保证赋值的合法性! #### function outer (){ var name = "梁朝伟"; var yanzhi = 100; return { setYanZhi : function(value){ return yanzhi < 100 ? yanzhi = 100 : alert('有眼光'); } } } var obj = outer(); obj.setYanZhi(101); // 有眼光; #### 2. 给函数提供一个私有的变量 #### // 获取某个元素下的依次所有的子孙元素; function outer(){ //创建一个空数组,用来存内部元素添加的子元素 var list = []; return function (ele){ var children = ele.children; for(var i = 0; i < children.length; i++){ // 把得到的每个子元素添加到list中 list.push(children[i]); // 继续调用getChildren函数 得到children[i]中的每个子元素 getChildren(children[i]); } return list; } } outer()(document.body); // 上面代码中,list数组就是每个内部函数的共同的仓库,只能再outer函数中使用这个数组; ### 使用闭包解决循环变量i的问题 ### // 假设页面中有10个div var divs = document.getElementsByTagName('div'); for(var i = 0; i < divs.length; i++){ //因为在for循环中,outer函数会在内存中生成10个, // 每一个函数中i的值对应0~9; function outer (){ var j = i; return function (){ alert(j); } } divs[i].onclick = outer(); } // 其实上面的代码还能再优化优化 // 优化代码如下 var divs = document.getElementsByTagName('div'); for(var i = 0; i < divs.length; i++){ // 这里的参数j就相当于 var j; divs[i].onclick = ( function (j){ return function (){ alert(j); } })(i); //这里的i相当于把i每一次的值当做实参传给j; } #### 与上面题目类型的还有一个关于延时器(setTimeout)的题; #### // 需求: 在for(i<10)循环中,让setTimeout访问i值,一次打印出0~9; for(var i = 0; i < 10; i++){ setTimeout(function(){ alert(i); },1000); } // 由于setTimeout是异步任务,延时器还未执行的时候for循环就完成了 // 上述代码中延时器中函数访问到的i值毫无疑问是10个10; //接下来 我们让延时器中函数的结果变成0~9; for(var i = 0; i < 10; i++){ /// 每次循环都会有一个函数outer中的j变量去存i的值; function outer(){ var j = i; return function(){ alert(j); } } setTimeout(outer(),1000); } //上面的代码可以再优化优化,把它改成自执行函数就会显得简洁很多了 // 所以我们再来改巴改巴!~ for (var i = 0; i < 10; i++) { setTimeout(( function(j) { return function() { console.log(j); } } )(i), 1000); }
还没有评论,来说两句吧...