• 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. python 基础 内置函数 和lambda表达式

    1.把任意数值转化为字符串有两种方法. (1)str()用于将数值转化为易于人读的形式.print(str("我是中国人"))>>>我是中国人 (2)repr() ...

  2. [转] 带你彻底理解RSA算法原理

    http://blog.csdn.net/dbs1215/article/details/48953589 1. 什么是RSA RSA算法是现今使用最广泛的公钥密码算法,也是号称地球上最安全的加密算法 ...

  3. 从图像中检测和识别表格,北航&微软提出新型数据集 TableBank

    纯学术 的识别表格的文章: http://hrb-br.com/5007404/20190321A0B99Y00.html https://github.com/doc-analysis/TableB ...

  4. OSWATCH安装

    .解压安装包 afadb2:/home/oracle$tar -xvf oswbb732.tar (注:先将安装包权限修改为oracle:oinstall,或者对应权限,以ORACLE用户进行解压) ...

  5. 复杂的动态布尔表达式性能评估(2)--Groovy实现

    前言: 规则引擎中, 往往涉及到多个条件构成了复杂布尔表达式的计算. 对于这类布尔表达式, 一是动态可变的(取决于运营人员的设定), 二是其表达式往往很复杂. 如何快速的计算其表达式的值, 该系列文章 ...

  6. easyui的DataGrid的单元格添加ProgressBar进度条

    网上的搜到的好多不能用,官方easy-ui使用进度条 <div id="p" class="easyui-progressbar" ></di ...

  7. s21day04 python笔记

    s21day04 python笔记 一.上周知识回顾及补充 回顾 补充 编译型语言和解释性语言 编译型:代码写完后,编译器将其变成成另外一个文件,然后交给计算机执行 常见的编译型语言:C,C++,Ja ...

  8. 20155219 2016-2017-2 《Java程序设计》第5周学习总结

    20155219 2016-2017-2 <Java程序设计>第5周学习总结 教材学习内容总结 异常处理 语法与继承构架 异常就是程序在运行时出现的不正常情况.java中的错误以对象的方式 ...

  9. python day 09 文件操作

    一 初识文件操作 使⽤用python来读写⽂文件是非常简单的操作. 我们使⽤用open()函数来打开⼀一个⽂文件, 获取到⽂文件句句柄. 然后通过⽂文件句句柄就可以进⾏行行各种各样的操作了了. 根据打 ...

  10. java-Random类

    1.Random类的概述和方法使用 * A:Random类的概述 * 此类用于产生随机数 * 如果用相同的种子创建两个 Random 实例,则对每个实例进行相同的方法调用序列,它们将生成并返回相同的数 ...