• 1.变量的作用域
  • 2.变量的生存周期
  • 3.闭包更多作用
    • 1.封装变量
    • 2.延续局部变量寿命
  • 4.闭包和面向对象设计
  • 5.闭包和内存管理

1.变量的作用域

var func = function(){
var a = 1;
}
func();
console.log(a); //输出undefined
var a = 1;
fun1 = function(){
var b = 2;
fun2 = function(){
var c = 3;
console.log(b); //输出 2
console.log(a); //输出 1
}
fun2();
console.log(c); //输出undefined
}
fun1();

2.变量的生存周期

var func = function(){
var a = 1;
return function(){
a++;
console.log(a);
}
}
var f = func();
f(); // 输出1
f(); // 输出2
f(); // 输出3
f(); // 输出4

当退出函数后,局部变量a并没有消失,而是似乎一致在某个地方存活着。这是因为当执行var f = func();时,f返回了一个匿名函数的引用,它可以访问到func()被调用时产生的环境,而局部变量a一致处于这个环境里。既然局部变量所在的环境还能被外界,这个局部变量就有了不被销毁的理由。这里产生了一个闭包结构,局部变量的声明看起来被延续了。

既然f返回了一个匿名的函数引用,那么下面的也符合闭包

var func = (function(){
var a = 1;
return function(){
a++;
console.log(a);
}
})();
f(); // 输出1
f(); // 输出2
f(); // 输出3
f(); // 输出4

再次变种为引用对象的方式

var func = {
a :0,
call:function(){
this.a++;
console.log(this.a);
}
}
func.call(); //输出1
func.call(); //输出2
func.call(); //输出3

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<script>
var nodes = document.getElementsByTagName('div');
for(var i =0;i<nodes.length;i++){
nodes[i].onclick=function(){
alert(i);
}
}
</script>
</body>
</html>

测试这段代码就会发现,无论点击哪个div,最后弹出的结构都是5,。这是因为div节点onclick事件是被异步出发的,当事件出发的时候,for循环早已结束,此时变量i的值已经是5,所以在div的onclick事件函数中顺着作用域链从内到外查找变量i时,查找到的值总是5。

解决方法是在闭包作用的帮助下,把每次循环的i值都封装起来。(就是把每个点击事件都独立放在内存里面。)

var nodes = document.getElementsByTagName('div');
for(var i =0;i<nodes.length;i++){
(function(i){
nodes[i].onclick=function(){
alert(i);
}
})(i);
}

3.闭包更多作用

1.封装变量

闭包可以帮组我们封装私有变量”

var mult = function(){
var a = 1;
for(var i =0;i <arguments.length;i++){
a = a*arguments[i];
}
return a;
}
console.log(mult(1,2,5));

mult函数接受一些number类型的函数,并返回这些参数的乘积。现在我们觉得对于这些那些参数来说,每次都进行计算是一种浪费,我们可以加入缓存机制来提高这个函数的性能。

var cache={};
var mult = function(){
var args = Array.prototype.join.call(arguments,','); //将参数对象变成一个字符串 args 1,2,3
if(cache[args]){
console.log('执行缓存');
return cache[args];
}
var a = 1;
for(var i=0;i<arguments.length;i++){
a = a*arguments[i];
}
return cache[args] = a;
}
console.log(mult(1,2,3)); //进行计算
console.log(mult(1,2,3)); //执行缓存,不用计算

继续封装减少页面全局变量

var mult = (function(){
var cache={}; //私有变量
return function(){
var args = Array.prototype.join.call(arguments,',');
if(cache[args]){
return cache[args];
}
var a = 1;
for(var i=0;i<arguments.length;i++){
a = a*arguments[i];
}
return cache[args] = a;
}
})()
console.log(mult(1,2,3)); //进行计算
console.log(mult(1,2,3)); //执行缓存,不用计算

提炼代码,独立模块

var mult = (function(){
var cache={}; //私有变量
var cala = function(){
var a = 1;
for(var i=0;i<arguments.length;i++){
a = a*arguments[i];
}
return a;
}
return function(){
var args = Array.prototype.join.call(arguments,',');
if(cache[args]){
return cache[args];
}
return cache[args] = cala.apply(null,arguments);
}
})();
console.log(mult(1,2,3)); //进行计算
console.log(mult(1,2,3)); //执行缓存,不用计算
2.延续局部变量的寿命
var report = function(src){
var img = new Image();
img.src = src;
}

利用闭包来延续img的使用

var report = (function(){
var imgs = []; //img就留在了内存里面
return function(src){
var img = new Image();
imgs.push(img);
img.src = src;
}
})();

4.闭包和面向对象

闭包:

var extent = function(){
var value =0;
return {
call:function(){
value++;
console.log(value);
}
}
}
var extent = extent();
extent.call(); //输出1
extent.call(); //输出2
extent.call(); //输出3

如果换成面向对象的写法就是

var extent = {
value :0,
call:function(){
this.value++;
console.log(this.value);
}
}
extent.call(); //输出1
extent.call(); //输出2
extent.call(); //输出3

5.闭包和内存管理

闭包是一个非常强大的特性,但人民对其他诸多误解,一种耸人听闻的说法就是闭包会造成内存泄漏。如果在将来需要回收这些变量,我们可以手动吧这些变量设置为null。

《JavaScript设计模式与开发》笔记 4.闭包的更多相关文章

  1. 《JavaScript设计模式与开发实践》读书笔记-基础知识

    笔记内容多摘录自<JavaScript设计模式与开发实践>(曾探著),侵删. 面向对象的JavaScript 1. 动态需要类型和鸭子类型 鸭子类型 如果它走起路来像鸭子,叫起来也是鸭子, ...

  2. 《Javascript设计模式与开发实践》--读书笔记

    第2章 this call apply bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用. bind( ...

  3. JavaScript设计模式与开发实践——读书笔记1.高阶函数(上)

    说来惭愧,4个多月未更新了.4月份以后就开始忙起来了,论文.毕设.毕业旅行等七七八八的事情占据了很多时间,毕业之后开始忙碌的工作,这期间一直想写博客,但是一直没能静下心写.这段时间在看<Java ...

  4. 《JavaScript设计模式与开发实践》整理

    最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...

  5. JavaScript设计模式与开发实践 - 单例模式

    引言 本文摘自<JavaScript设计模式与开发实践> 在传统开发工程师眼里,单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返 ...

  6. 《javascript设计模式与开发实践》--- (单一职责原则)

    看的这本书叫<JavaScript设计模式与开发实践> 先规划一下看书的顺序,基础知识我已经大概的浏览了一遍了,没有留下笔记,以后有时间还会补上.本来打算顺着看的.但是我感觉我很难短时间内 ...

  7. JavaScript设计模式与开发实践 - 观察者模式

    概述 观察者模式又叫发布 - 订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个目标对象(为了方便理解,以下将观察者对象叫做订阅者,将目标对象叫做 ...

  8. JavaScript设计模式与开发实践 - 策略模式

    引言 本文摘自<JavaScript设计模式与开发实践> 在现实中,很多时候也有多种途径到达同一个目的地.比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但 ...

  9. 《JavaScript设计模式》读书笔记——灵活的语言

    最近在读JavaScript设计模式这本书,准备搞一个系列来记录所学所想,其实主要原因是方便以后查阅. 第一章主要介绍了JS函数的不同定义与使用方法,用自己的方法去模拟类也是它的独有魅力所在. 首先, ...

  10. 《javascript设计模式与开发实践》读书笔记之函数,this,闭包

    一.函数基本理论 function compare(val1,val2){ return val1 - val2; }var result = compare(5,10); 1,函数的定义没什么意义, ...

随机推荐

  1. thinkphp5.0--验证

    我才知道原来验证有两种类型,独立验证和验证器,当然我们工作中肯定用验证器喽,代码的封装性也好很多,其实我觉得代码的维护性也好很多; 独立验证: //独立验证$data = [ 'name' => ...

  2. 百练1678-整数的个数-2015正式A题

    A:整数的个数 总时间限制:  1000ms 内存限制:  65536kB 描述 给定k(1< k < 100)个正整数,其中每个数都是大于等于1,小于等于10的数.写程序计算给定的k个正 ...

  3. 倍增求lca

    /* 节点维护的信息多样 如果用树状数组维护到根节点的边权或者点权, 可以直接插入点权和边权值,不需要预处理, 但是记得一定要使用ot[]消除影响.即差分. Housewife Wind 这个坑踩得死 ...

  4. parson json解析

    最近交互数据中用到JSON数据,很多年以前用过CJSON解析和生成JSON数据,貌似CJSON已经发展成为了libjson,本打算用libjson库,不过其提供的解析JSON方式采用了回调,是测试过程 ...

  5. Gym102040 .Asia Dhaka Regional Contest(寒假自训第9场)

    B .Counting Inversion 题意:给定L,R,求这个区间的逆序对数之和.(L,R<1e15) 思路:一看这个范围就知道是数位DP. 只是维护的东西稍微多一点,需要记录后面的各种数 ...

  6. eclipse 启动tomcat 出现错误Could not publish server configuration: null. java.lang.NullPointerException

    若出现以上错误,则很有可能是修改了conf/server.xml的内容,将改过的地方改回去,然后重启tomcat 就可以啦

  7. Red Hat OpenShift

    Core Concepts 基本概念 Master Master监控其他Node和Pod 提供Web Console Node Node是k8s的工作机器 Node中运行Pod,pod可以在node中 ...

  8. 【BZOJ4817】【SDOI2017】树点染色

    不算学会lct...... 原题: Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种 ...

  9. 试用 openresty/lua-resty-shell

    openresty/lua-resty-shell 是当前最新rc 版本内置的shell 功能,我们可以用来执行一个脚本,以及命令 还是比较方便的. 测试集成了一个oreilly电子书下载的功能 环境 ...

  10. benthos v1 的一些新功能

    主要从视频文件截取,暂时github 上还没有很全的相关文档 v1目标 config lint processor error 处理 subprocess processor awk processo ...