1.返回值(最常用)

	//1.返回值 最常用的
function fn(){
var name="hello";
return function(){
return name;
}
}
var fnc = fn();
console.log(fnc())//hello

这个很好理解就是以闭包的形式将 name 返回。

2.函数赋值

        var fn2;
function fn(){
var name="hello";
//将函数赋值给fn2
fn2 = function(){
return name;
}
}
fn()//要先执行进行赋值,
console.log(fn2())//执行输出fn2

在闭包里面给fn2函数设置值,闭包的形式把name属性记忆下来,执行会输出 hello。

3.函数参数

		function fn(){
var name="hello";
return function callback(){
return name;
}
}
var fn1 = fn()//执行函数将返回值(callback函数)赋值给fn1, function fn2(f){
//将函数作为参数传入
console.log(f());//执行函数,并输出
}
fn2(fn1)//执行输出fn2

用闭包返回一个函数,把此函数作为另一个函数的参数,在另一个函数里面执行这个函数,最终输出 hello

4.IIFE(自执行函数)

	(function(){
var name="hello";
var fn1= function(){
return name;
}
//直接在自执行函数里面调用fn2,将fn1作为参数传入
fn2(fn1);
})()
function fn2(f){
//将函数作为参数传入
console.log(f());//执行函数,并输出
}

直接在自执行函数里面将封装的函数fn1传给fn2,作为参数调用同样可以获得结果 hello

5.循环赋值

	//每秒执行1次,分别输出1-10
for(var i=1;i<=10;i++){
(function(j){
//j来接收
setTimeout(function(){
console.log(j);
},j*1000);
})(i)//i作为实参传入
}

如果不采用闭包的话,会有不一样的情况,可以看我自己 闭包 的文章。

6.getter和setter

function fn(){
var name='hello'
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

第一次输出 hello 用setter以后再输出 world ,这样做可以封装成公共方法,防止不想暴露的属性和函数暴露在外部。

7.迭代器(执行一次函数往下取一个值)

		var arr =['aa','bb','cc'];
function incre(arr){
var i=0;
return function(){
//这个函数每次被执行都返回数组arr中 i下标对应的元素
return arr[i++] || '数组值已经遍历完';
}
}
var next = incre(arr);
console.log(next());//aa
console.log(next());//bb
console.log(next());//cc
console.log(next());//数组值已经遍历完

8.首次区分(相同的参数,函数不会重复执行)

 var fn = (function(){
var arr=[];//用来缓存的数组
return function(val){
if(arr.indexOf(val)==-1){//缓存中没有则表示需要执行
arr.push(val);//将参数push到缓存数组中
console.log('函数被执行了',arr);
//这里写想要执行的函数
}else{
console.log('此次函数不需要执行');
}
console.log('函数调用完打印一下,方便查看已缓存的数组:',arr);
}
})(); fn(10);
fn(10);
fn(1000);
fn(200);
fn(1000);

执行结果如下:

可以明显的看到首次执行的会被存起来,再次执行直接取。

9.缓存

//比如求和操作,如果没有缓存,每次调用都要重复计算,采用缓存已经执行过的去查找,查找到了就直接返回,不需要重新计算

	 var fn=(function(){
var cache={};//缓存对象
var calc=function(arr){//计算函数
var sum=0;
//求和
for(var i=0;i<arr.length;i++){
sum+=arr[i];
}
return sum;
} return function(){
var args = Array.prototype.slice.call(arguments,0);//arguments转换成数组
var key=args.join(",");//将args用逗号连接成字符串
var result , tSum = cache[key];
if(tSum){//如果缓存有
console.log('从缓存中取:',cache)//打印方便查看
result = tSum;
}else{
//重新计算,并存入缓存同时赋值给result
result = cache[key]=calc(args);
console.log('存入缓存:',cache)//打印方便查看
}
return result;
}
})();
fn(1,2,3,4,5);
fn(1,2,3,4,5);
fn(1,2,3,4,5,6);
fn(1,2,3,4,5,8);
fn(1,2,3,4,5,6);

输出结果:

转载于:https://blog.csdn.net/dkm123456/article/details/111644638

理解js闭包9大使用场景的更多相关文章

  1. javascript深入理解js闭包(转)

    javascript深入理解js闭包 转载  2010-07-03   作者:    我要评论 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. ...

  2. 理解JS闭包

    从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解 ...

  3. 理解JS闭包的几个小实验

    学了JavaScript有一段时间了,但是对闭包还是不太理解,于是怀着心中的疑问做了几个小实验,终于有点明白了. 首先看一下MDN上的定义:闭包是函数和声明该函数的词法环境的组合. 简单来说,闭包是一 ...

  4. javascript深入理解js闭包(个人理解,大神勿喷)

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  5. javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  6. 深入理解JS闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  7. javascript深入理解js闭包[转]

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  8. (转)javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  9. javascript深入理解js闭包(看了挺多的,感觉这篇比较透彻)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...

随机推荐

  1. sqli-labs第5关布尔盲注pyhton脚本

    import requests import os #此函数先判断数据库长度 def length(url,str): num = 1 while True: str_num = '%d' %num ...

  2. VS中RDLC提示类型不一致

    错误"基类包括字段"XXXXXXX",但其类型(Microsoft.Reporting.WebForms.ReportViewer)与控件(Microsoft.Repor ...

  3. 获取Web项目中的控制器类以及类中Action方法

    前言 在使用时需要修改命名空间.需要过滤控制器.需要过滤Action方法.结果生成表的插入语句. 代码 public ActionResult ReloadData() { #region 获取所有的 ...

  4. EF生成模型时Disigner中无信息

    原博文 http://blog.sina.com.cn/s/blog_a1b63a730101ezs4.html 说明 DbContext是对ObjectContext的简化封装.原来的ObjectC ...

  5. idea修改项目名导致无法找到主类

    描述 本地创建项目copy或者是修改项目名和文件夹名称后 启动springboot项目失败 控制台报错 错误无法找到主类 解决办法 1. 求助互联网得知 需要执行 mvn clean install( ...

  6. OAuth2.0的四种授权模式(转)

    1. OAuth2简易实战(一)-四种模式 1.1. 隐式授权模式(Implicit Grant) 第一步:用户访问页面时,重定向到认证服务器. 第二步:认证服务器给用户一个认证页面,等待用户授权. ...

  7. 阿里巴巴java开发手册-泰山版 下载

    最近,阿里的<Java开发手册>又更新了,这个版本历经一年的修炼,取名:<Java开发手册(泰山版)>正式出道.正所谓无规矩不成方圆,在程序员的世界里,也存在很多规范,阿里出版 ...

  8. spring传播机制注意点

    在同一个类里面spring的传播机制是不起作用的比如说在执行saveA方法的时候调用C方法插入C设置的传播属性是不使用事物 但是执行的效果是saveA方法抛出异常后导致C的记录回滚了也就是说明C方法设 ...

  9. [leetcode]205. Isomorphic Strings同构字符串

    哈希表可以用ASCII码数组来实现,可以更快 public boolean isIsomorphic(String s, String t) { /* 思路是记录下每个字符出现的位置,当有重复时,检查 ...

  10. Arduino IDE开发ESP8266-01S连接MQTT服务器 控制继电器点亮LED

    准备条件: 1.Arduino IDE 2.ESP-01S模块 2.MQTT服务器 3.手机热点或路由器热点 Wi-Fi芯片 默认订阅的主题是  "开关控制" 当你发送主题  &q ...