理解js闭包9大使用场景
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大使用场景的更多相关文章
- javascript深入理解js闭包(转)
javascript深入理解js闭包 转载 2010-07-03 作者: 我要评论 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. ...
- 理解JS闭包
从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解 ...
- 理解JS闭包的几个小实验
学了JavaScript有一段时间了,但是对闭包还是不太理解,于是怀着心中的疑问做了几个小实验,终于有点明白了. 首先看一下MDN上的定义:闭包是函数和声明该函数的词法环境的组合. 简单来说,闭包是一 ...
- javascript深入理解js闭包(个人理解,大神勿喷)
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- javascript深入理解js闭包
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- 深入理解JS闭包
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- javascript深入理解js闭包[转]
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- (转)javascript深入理解js闭包
一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...
- javascript深入理解js闭包(看了挺多的,感觉这篇比较透彻)
闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...
随机推荐
- Webpack的学习总结(1)
入门 Webpack,看这篇就够了 入门 Webpack,看这篇就够了 写在前面的话 一个基础的webpack配置文件 什么是WebPack,为什么要使用它? WebPack和Grunt以及Gulp相 ...
- Django + FastDFS (分布式远程服务器存储文件)
之前随笔过一篇Docker来搭建分布式文件系统FastDfs就跳过了 https://www.cnblogs.com/xcsg/p/10901461.html FastDFS的Python (dja ...
- rocketMq broker.conf全部参数解释
#4.7.1版本 #所属集群名字brokerClusterName=rocketmq-cluster#broker名字,名字可重复,为了管理,每个master起一个名字,他的slave同他,eg:Am ...
- python初学者-输入一个数判断奇偶性
num = int(input("请输入一个整数:")) if num%2 == 0: print("这个数是偶数",num) else: print(&quo ...
- 3.自定义view-TextView变色
1.效果 2.实现原理 自定义Textview,重写onDraw方法,将画布分成两部分,用不同颜色的画笔画 核心代码: @Override protected void onDraw(Canvas c ...
- RocketMQ(七):高性能探秘之线程池
上一篇文章讲了如何设计和实现高并发高性能的应用,从根本上说明了一些道理.且以rocketmq的mappedFile的实现作为一个突破点,讲解了rocketmq是如何具体实现高性能的.从中我们也知道,m ...
- 关于META-INF下的spring.factories文件
spring.factories 文件是springboot提供的一种实例化bean方式 org.springframework.boot.autoconfigure.EnableAutoConfig ...
- 使用pdf2htmlEX将pdf文件转为html
https://github.com/coolwanglu/pdf2htmlEX 参考github文档,转换出来的的效果貌似很好,可以参考OFFICE 文档转换为html在线预览. pdf2swf 和 ...
- 【代码周边】-GitHub笔记
------------恢复内容开始------------ 程序员的宝库github是个好东西,其中开源的项目足够我们的使用,但是如何去精准的获取我们的项目是很多初学者的问题.特别是英语不好的我,一 ...
- Spring boot 启动错误处理:Action: Consider the following: If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. If you have database settings to be loaded from a particular...
错误原因 在pom中引入了mybatis-spring-boot-starter ,Spring boot默认会加载org.springframework.boot.autoconfigure.jdb ...