目录
匿名函数
含义:匿名函数即没有函数名的函数
匿名函数创建:将匿名函数用括号包裹,后面再加一个括号用于执行或者传值调用
//匿名函数创建
/* (function(){
console.log("匿名函数"); //输出:匿名函数
})() */ //加上括号执行函数体内语句
(function(a,b){
console.log(a+b); //输出3
})(1,2); //括号内输入参数进行传值
闭包函数
含义
函数有权访问另一函数作用域内变量的函数,闭包函数本质上是函数的嵌套
特性
1.函数内部可以引用函数外部参数和变量
//函数内部可以引用函数外部参数和变量
function a(){
var name='zhangsan';
return function(){ //返回匿名函数,这里是一个闭包
return name; //使用父函数中声明变量
}
}
var b=a();
console.log(b()); //输出:zhangsan
强调:闭包中局部变量是引用而不是拷贝,通俗点可以理解为闭包保存的是一个环境而不是仅仅固定住某个变量。例如下面的例子,输出数组中的值全部是10,保存的并不是变量i在某个时候的值,而是这个环境下的值,也就是最后的i=10
//闭包中局部变量是引用而不是拷贝
/*
此时的i仅是i的引用而不是i的值
外部函数执行完毕后,i的值是10
此时i的值被赋值给a数组,i=10
*/
function fun(){
let a = new Array();
for (var i = 0; i < 10; i++){
a[i] = function() {
return i;
};
}
return a;
}
var a = fun();
for(var j=0;j<10;j++){
console.log(a[j]()); //全部输出10
}
上述例子要想 解决也是可以的,使用匿名函数的自我执行特性,在后面加上括号进行传值
/*
此时的i只是函数参数
函数参数按值传递
故此时匿名函数被强制执行
*/
function fun(){
let a = new Array();
for (var i = 0; i < 10; i++){
a[i] = function(num) {
return function(){
return num;
}
}(i);
}
return a;
}
var a = fun();
for(var j=0;j<10;j++){
console.log(a[j]()); //输出 0 1 2 3 4 5 6 7 8 9
}
2.参数和变量不会被垃圾回收机制回收
//参数和变量不会被垃圾回收机制回收
function a(){
var num=1;
return function(){ //返回匿名函数
var n=0;
console.log("n=",++n);
console.log("num=",++num);
}
}
var b=a();
b(); //输出 n=1 num=2
b(); //输出 n=1 num=3
应用
已知许多编程语言c、c++、Java等支持将方法声明为私有,也就是只能被同一个类中的其他方法调用。但是JavaScript没有此类原生支持,故可以利用闭包来模拟私有方法
私有方法好处:
1.有利于限制对代码的访问
2.提供了管理全局命名空间的强大能力,避免非核心的方法弄乱了代码的公共接口部分。
闭包模拟私有方法
如下例所示,创建一个立即执行的匿名函数为共享环境,环境中包含私有项privateFun变量和私有项change函数,这两项无法再匿名函数外部直接访问,需要通过匿名函数返回的公共函数get1、get2、sets进行访问
//闭包模拟私有方法
var Fun=(function(){
var privateFun=1; //创建私有项privateFun变量
function change(a){ //创建私有项change函数
privateFun += a;
}
return{
set1:function(){
change(2);
},
set2:function(){
change(6);
},
gets:function(){
return privateFun;
}
}
})();
console.log(Fun.gets()); //输出1
Fun.set1();
console.log(Fun.gets()); //输出3
Fun.set2();
console.log(Fun.gets()); //输出9
优缺点
优点
1.实现封装,保护函数内的变量安全,以防止变量流入其他环境造成命名冲突
2.内存中维持一个变量,用作缓存(l滥用也是一项缺点,过度消耗内存)
3.匿名自执行函数可以减少内存消耗
缺点
1.被引用的私有变量不能销毁,滥用会导致消耗内存(解决方法是使用完后手动为其赋值为null)
2.闭包涉及跨域访问,会导致性能损失(可以通过把跨作用域变量存储在局部变量中,直接访问局部变量,以减轻对执行速度的影响)