一个函数的作用域可以访问另一个函数的局部变量,这个变量所在的函数就是闭包函数。
闭包使得内部函数可以访问外部函数的属性(变量或方法)
1.返回值
function fn(){
let name="123";
return function(){
return name;
}
}
let fnc=fn();
console.log(fnc()); //123
//以闭包的行事将name变量返回;
或者:console.log(fn()()); //123
2.函数赋值
var fn2;
function fn(){
var name="123";
fn2=function(){
retun name;
}
}
fn();//先执行函数进行赋值
console.log(fn2());//123
3.函数参数(有点类似回调)
function fn(){
var name="123";
return function callback(){
return name;
}
}
let fn1=fn();//执行函数将返回值(callback函数)赋值给fn1
function fn2(f){
//将函数作为参数传入
console.log(f());//执行函数,并输出
}
fn2(fn1); //123
等价于:fn2(fn()); //123 因为fn1=fn();
用闭包返回一个函数,把函数作为另一个函数的参数,在另一个函数里面执行这个函数,最终输出123;
4.IIFE(自执行函数)
(function(){
var name="123";
let fn1=function(){
return name;
}
//直接在自执行函数里面调用fn2,将fn1作为参数传入
fn2(fn1);
})()
function fn2(f){
//将函数作为参数传入
console.log(f());//执行函数,并输出
}
//直接在自执行函数里面将封装的函数fn1传给fn2,作为参数调用者可以获得结果123
5.循环赋值
//每执行1次,分别输出1-10
for(let i=0;i<=10;i++){
(function(j){
//j是形参 接收
setTimeout(function(){
console.log(j);
},1000*j)
})(i)//i作为实参传入
}
6.getter和setter
function fn(){
var name="123";
setName=function(n){
name=n
}
getName=function(){
return name;
}
//将setName,getName作为对象的属性返回
return {
setName:setName,
getName:getName
}
}
var fn1=fn();//返回对象 属性setName和getName是两个函数
console.log(fn1.getName());//getter
fn1.setName("world");//setter修改闭包的name
console.log(fn1.getName());//getter
7.迭代器(执行一次函数往下去取下一个值)
var arr=[1,2,3]
function incre(arr){
let i=0;
return function(){
//这个函数每次被执行都返回数组arr中i下标对应的元素
rerurn arr[i++] || '完成'
}
}
var next=incre(arr);
console.log(next());//1
console.log(next());//2
console.log(next());//3
console.log(next());//完成
8.首次区分(相同的参数,函数不会重复执行)
var fn=(function(){
var arr=[]l
return function(val){
if(arr.indexOf(val)==1){
arr.push(val);
consle.log('函数执行完了')
//这里写想要执行的函数
}else{
console.log('此次函数不需要执行');
}
console.log('函数调用完打印一次',arr);
}
})();
fn(10);
fn(10);
fn(1000);
fn(100);
fn(1000);
9.缓存
//比如求和操作,如果没有缓存,每次调用都要重复计算,采用缓存已经执行过的去查找,查找到了就直接返回,不需重新计算
var fn=(function(){
var cache={};
var calc=function(arr){
var sum=0;
//求和
for(let i==0;i<arr.length;i++){
sum+=arr[i];
}
return sum;
}
return function(){
var args=Array.prototype.slice.call(arguments,0);
var key=args.join(".");
var result,tSum=cache[key];
if(Sum){
console.log('从缓存中取:',cache);
result=tSum;
}else{
result=cache[key]=calc(args);
console.log('存入缓存:',cache);
}
return result;
}
})();
fn(1,2,3)
fn(1,2,3,4,5)
回调函数也是闭包
function fn(zy,fn){
console.log(`完成${zy}作业。`);
var isFinished=true;
let timer=setTimeout(()=>{
if(isFinished){
console.log("看完电视了");
fn("看完电视了");
}else{
console.log("作业没完成,还在继续写作业");
fn("作业没完成,还在继续写作业");
}
},2000);//2秒回调
}
//需求 做完数学作业,妈妈允许我看电视
fn("数学",function(res){
console.log(res);
})