js 匿名函数和闭包

匿名函数和闭包

https://www.cnblogs.com/xiaowie/p/10277483.html 填写了注释

匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数。声明:本节内容需要有面向对象和少量设计模式基础,否则无法听懂。

 

 

// //普通函数
// function box(){
//     return 'lee';
// };

// //匿名函数
// function(){                        //执行的时候会显示错误
//     return 'lee';
// };

//把匿名函数自我执行的返回值赋值给变量
var b=function(){                        //单独的匿名函数,是无法执行的 就算执行也无法调用
    return 'lee';
};

alert(b);                    //这样会打印出匿名函数的结构(包括后面的注释)
alert(b());                 //这样会打印出匿名函数的返回值

 

 

// 匿名函数自我执行
(function (){                        //(匿名函数)(); 第一圆括号放匿名函数,第二个圆括号执行
    return 'lee';            //()表示执行
})();


alert((function (){
    return 'lee';
})());

 

//自我执行匿名函数的传参

alert((function(age,name){
    return age+name;
})(100,200)
);

//函数里的匿名函数
function box(){
return function(){ //闭包
return 'lee';
}
};

alert(box()()); //box() 返回是匿名函数的结构 box()()返回函数中匿名函数的返回值

 

闭包:

  闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。

简单说 :闭包:A函数中嵌套着B函数,B程序中有用到A的变量,当外部函数C调用函数A时,虽然A已经执行完毕,理论上函数执行完毕,它就要被弹出栈,但是由于B要用到A,所以A的变量被保存到内存中不被销毁,我们称函数B是闭包。

 

//通过闭包可以返回局部变量
function box(){
    return function(){                    //通过匿名函数返回box()局部变量
        return 'Lee';
    };
};

alert(box()());                    //通过box()()来直接调用匿名函数返回值
var b=box();            
alert(b());                        //另一种调用匿名函数返回值

 

使用闭包有一个优点,也是他的缺点;就是可以把局部变量留在内存中,可以避免使用全局变量。(全局变量污染导致应用程序不可预测性,每个模块都可调用必将引来灾难,所以拓建使用私有的,封装的局部变量)

 

//全局变量累加
// var b=100;
// function box(){
//         b++;
// };

// alert(b);
// box();
// alert(b);

//使用匿名函数实现局部变量驻留内存中从而累加
function box(){
    var age=100;
    return function(){
        age++;
        return age;
    };
};

var b=box();
alert(b());         //每次都要匿名函数 101
alert(b());        //102
alert(b());        //103
alert(b());        //104

 

 

//循环里的匿名函数的取值问题1
function box(){
    var arr=[];
    for(var i=0;i<5;i++){
        arr[i]=function(){
            return i;
        };    
    };
    return arr;
};

var b=box();
for(var i=0;i<5;i++){
    alert(b[i]());        //这么写取值返回的都是5 只执行一次
}
//循环的匿名函数取值问题2

function box(){
    var arr=[];
    for(var i=0;i<5;i++){
        arr[i]=(function(num){            //通过自我及时执行匿名函数
            return num;
        })(i);    
    };
    return arr;
};


var b=box();
for(var i=0;i<5;i++){
    alert(b[i]);        //这么写取值返回的都是5
}

//循环里的闭包的取值问题3
function box(){
    var arr=[];
    for (var i =0; i<5;i++) {
        arr[i]=(function(num){            //arr【0】=0,arr[1]=1,arr[2]=2.......
            return function(){            //闭包可以将变量驻留到内存中。
                return num
            };
        })(i);
    }


    return arr;
};


var b=box();
for(i=0;i<5;i++){
    alert(b[i]());
};

 

 内存泄漏

  由于IE的JScript和DOM对象使用不同的垃圾收集方式,因此闭包在IE中会导致一些问题,就是内存泄漏的问题,也就是无法销毁驻留在内存中的元素,以下代码有连个知识点还没有学习到,以个是DOM,一个是事件

 

function divShow(){
    var b=document.getElementById("di");      //b  用完之后会一直驻留到内存中
    b.onclick=function(){
        alert(b.innerHTML);      //这里用b导致内存泄漏
    };
}

divShow();

 

模仿块级作用域

  javascript没有块级作用的概念

 

//块级作用域(私有作用域)

function box(count){
    for(var i=0;i<count;i++)    //i不会因为离开了for块就失效
        var i;                    //就算重新声明,也不会前面的数据
        alert(i);               
};

box(2);

 

  以上两个例子,说明javascript没有块级语句的作用域,if(){}  for(){} 等没有作用域,如果有,出了这个范围:就应该被销毁了,就算重新声明同一个变量也不会改变他的值。

  javascript不会提醒你是否多次声明了同一个变量:遇到这种情况,它只会对后续I的声明视而不见(如果初始化了,当然还会被执行)使用模仿块级作用域可避免这个问题。

 

//模仿块级作用域(私有作用域)

function box(count){
    (function(){      //包含自我执行函数,就可以实现私有作用域
        for(var i=0;i<count;i++)   
        alert(i); 
})();
    alert(i);    //报错,无法访问  被销毁了
    };
    
box(2);       

 

   使用了块级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时被销毁,这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数,一般来说,我们都应该尽可能少像全局作用域中添加变量和函数,在大型项目中,多人开发的时候,过多的全局变量和函数很容易导致命名冲突,引起灾难性的后果,如果采用块级作用域(私有作用域)每个开发者既可以使用自己的变量,又不必担心搞乱全局作用域。

 私有变量

  javascript没有私有属性的概念,所有的对象属性都是共有的,不过,却有一个私有变量的概念,任何在函数中定义的变量,都可以认为是私有变量,因为不能再函数的外部访问这些变量

function box(){
    var b=100;            //私有变量,外部无法访问
};

而通过函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量,而利用这一点,都可以创建用于访问私有变量的公有方法

 

//对象共有化
function Box(){
    this.age=100;                    //属性,共有的
    this.run=function(){            //方法,共有的
        return '运行中....';
    }
};

var box=new Box();
alert(box.age);           //返回100
alert(box.run());        //返回运行中



//私有化
function Box(){
     var age=100;                    //私有属性
    function run(){                    //私有方法
        return '运行中';
    };
    this.publicGo=function (){        //对外可见的公共接口,特权方法
        return age+run();
    };
};

var box=new Box();
alert(box.age);                    //返回 undefined   找不到
alert(box.run());                //返回 undefined   找不到
alert(box.publicGo());            //返回 100 运行中

 

 

//通过构造函数传参
function Box(value){
    var age=value;
    this.getAge=function(){
        return age;
    };
};

var box=new Box('杜伟');
alert(box.getAge());

 

什么叫单例:就是永远只实例化一次,其实就是字面量对象声明方式(无法第二次实例化就叫单例)。

模块模式

 

var box={                //这样写其实已经实例化了
    age:100,
    run:function(){            
        return '运行中';
    }
};

alert(box.age);    //直接就可以调用
alert(box.run());

 

 

 

//字面量私有化

var box=function(){
    var age=100;                //私有变量
    function run(){                //私有函数
        return '运行中....';
    };
    return {                    //返回对象
        publicGo:function (){    //对外公共接口的特权方法
            return age+run();
        }
    };
}();

alert(box.publicGo());

 

字面量的对象声明,其实在设计模式中可以看作是一种单例模式,所谓单例模式,就是永远保持对象的一个实例

 

 

 

 

 

 

匿名函数,也称为拉姆达函数,是一种使用JavaScript函数的强大方式。以下总结了匿名函数的特点: 任何函数表达式从技术上说都是匿名函数,因为没有引用它们的确定的方式; 在无法确定如何引用函数的情况下,递归函数就会变得比较复杂; 递归函数应该始终使用arguments.callee来递归地调用自身,不要使用函数名--函数名可能会发生变化。 当在函数内部定义了其他函数时,就创建了闭包闭包有权访问包含函数内部的所有变量,原理如下: 在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域; 通常,函数的作用域及其所有变量都会在函数执行结束后被销毁; 但是,当函数返回了一个闭包时,这个函数的作用域将会一直在内存中保存到闭包不存在为止;使用闭包可以在JavaScript中模仿块级作用域(JavaScript本身没有块级作用域的概念),要点如下: 创建并立即调用一个函数,这样既可以执行其中的代码,又不会在内存中留下对该函数的引用; 结果就是函数内部的所有变量都会被立即销毁--除非将某些变量赋值给了包含作用域(即外部作用域)中的变量。 闭包还可以用于在对象中创建私有变量,相关概念和要点如下: 即使JavaScript中没有正式的私有对象属性的概念,但可以使用闭包来实现公有方法,而通过公有方法可以访问在包含作用域中定义的变量; 有权访问私有变量的公有方法叫做特权方法; 可以使用构造函数模式、原型模式来实现自定义类型的特权方法,也可以使用模块模式、增强的模块模式来实现单例的特权方法。 JavaScript中的匿名函数闭包都是非常有用的特性,利用它们可以实现很多功能。不过,因为创建闭包必须维护额外的作用域,所以过度使用它们可能会占用大量内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值