闭包

闭包的概念

函数执行造成一个私有做用域,保护里面的私有变量不受外界的干扰,这种保护机制叫作闭包。闭包

一个简单的闭包:函数

var utils = (function(){
    return {
        
    }
})()
复制代码

闭包的做用

  • 保护(保护私有做用域不受外界干扰)
  • 保存(造成一个不销毁的私有做用域)

何时用到闭包

  1. 在团队开发过程当中,咱们一般会把本身的代码存放在一个私有做用域中,若是别人须要使用某些方法的话,能够经过return或者window.xxx暴露在全局下。this

  2. jQuery源码也是利用这种保护机制的spa

    ~function(){
         var jQuery = function(){
             
         }
         window.$=window.jQuery=jQuery
     }()
    复制代码
  3. 闭包解决选项卡问题3d

    <div class="tabBox" id="tabBox">
             <ul>
                 <li>标题1</li>
                 <li>标题2</li>
                 <li>标题3</li>
             </ul>
             <div class="selected">content1</div>
             <div>content2</div>
             <div>content3</div>
         </div>
     
         var tabBox = document.getElementById('tabBox'),
             oList = tabBox.getElementsByTagName('li'),
             oDivList = tabBox.getElementsByTagName('div');
         function changeTab(index){
             //index 存储当前点击li的索引
             for(var i=0;i<oList.length;i++){
                 oList[i].className = oDivList[i].className = null //清除样式
             }
             oList[i].className = oDivList[i].className = 'selected'
         }
         for(var i=0;i<oList.length;i++){
             oList[i].onclick = function(){
                 //三次循环给三个li都绑定了一个方法,可是都没有执行,当循环结束了,i此时为3,
                 //等到点击的时候,就没法实现想要的效果了
                 changeTab(index)
             }
         }
    复制代码

解决办法是:code

  1. 自定义属性方式(能够给当前元素加一个属性)cdn

    for(var i=0;i<oList.length;i++){
         oList[i].myIndex = i;
         oList[i].onclick = function(){
             changeTab(this.myIndex)
         }
     }
    复制代码
  2. 闭包机制blog

    for(var i=0;i<oList.length;i++){
         oList[i].onclick = (function(i){
             //执行自执行函数首先会造成一个私有做用域
             //接下来 形参赋值 i=0,i=1,i=2
             return function(){
                 changeTab(i)
             }
         })(i)
     }
     //造成不销毁的私有做用域,不必定要有return,咱们也能够写成这样
     for(var i=0;i<oList.length;i++){
         (function(i){
             oList[i].onclick = function(){
                 //oList[i].onclick占用了返回的function,因此这个做用域也不会被销毁
                 changeTab(i)
             }
         })(i)
     }
    复制代码

如今有这样一道题索引

function fn(){
    var i=1;
    return function(n){
        console.log(n + i++)
    }
}
var f= fn()
f(10) // 11
fn()(10) //11
f(20) //22
fn()(20) //21
复制代码

首先咱们考虑变量提高内存

function fn(){ //fn内部会造成一个私有做用域,在私有做用域内,会发生形参赋值和变量提高,在这里并无形参传递,咱们只考虑变量提高
    var i=1;
    return function(n){ //return 引用类型的值才会让私有做用域不销毁
        console.log(n + i++) // 先把i=1赋值给结果,而后i本身再加1
    }
}
var f;
f= fn() //把fn执行的返回结果赋值给f 实际上f是function(n){console.log(n + i++)}
f(10) //把fn执行的返回结果再执行,而且给它传递一个参数10
fn()(10)
f(20)
fn()(20)
复制代码

函数执行返回了一个 引用数据类型堆内存的地址(而且堆内存隶属于这个做用域),在外面有一个变量接收了这个返回值,此时当前做用域就不能销毁(想要销毁,只须要让外面的变量赋值为null)

闭包与this问题

var num = 1,
    obj = {
        num:2,
        fn:(function(num){
            this.num*=2;
            num+=2;
            return function(){
                this.num*=3;
                num++;
                console.log(num)
            }
        })(num)
    }
var fn = obj.fn;
fn();
obj.fn();
console.log(num,obj.num)
复制代码

相关文章
相关标签/搜索