《JavaScript设计模式与开发》笔记 4.闭包
- 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.闭包的更多相关文章
- 《JavaScript设计模式与开发实践》读书笔记-基础知识
笔记内容多摘录自<JavaScript设计模式与开发实践>(曾探著),侵删. 面向对象的JavaScript 1. 动态需要类型和鸭子类型 鸭子类型 如果它走起路来像鸭子,叫起来也是鸭子, ...
- 《Javascript设计模式与开发实践》--读书笔记
第2章 this call apply bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用. bind( ...
- JavaScript设计模式与开发实践——读书笔记1.高阶函数(上)
说来惭愧,4个多月未更新了.4月份以后就开始忙起来了,论文.毕设.毕业旅行等七七八八的事情占据了很多时间,毕业之后开始忙碌的工作,这期间一直想写博客,但是一直没能静下心写.这段时间在看<Java ...
- 《JavaScript设计模式与开发实践》整理
最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...
- JavaScript设计模式与开发实践 - 单例模式
引言 本文摘自<JavaScript设计模式与开发实践> 在传统开发工程师眼里,单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返 ...
- 《javascript设计模式与开发实践》--- (单一职责原则)
看的这本书叫<JavaScript设计模式与开发实践> 先规划一下看书的顺序,基础知识我已经大概的浏览了一遍了,没有留下笔记,以后有时间还会补上.本来打算顺着看的.但是我感觉我很难短时间内 ...
- JavaScript设计模式与开发实践 - 观察者模式
概述 观察者模式又叫发布 - 订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个目标对象(为了方便理解,以下将观察者对象叫做订阅者,将目标对象叫做 ...
- JavaScript设计模式与开发实践 - 策略模式
引言 本文摘自<JavaScript设计模式与开发实践> 在现实中,很多时候也有多种途径到达同一个目的地.比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但 ...
- 《JavaScript设计模式》读书笔记——灵活的语言
最近在读JavaScript设计模式这本书,准备搞一个系列来记录所学所想,其实主要原因是方便以后查阅. 第一章主要介绍了JS函数的不同定义与使用方法,用自己的方法去模拟类也是它的独有魅力所在. 首先, ...
- 《javascript设计模式与开发实践》读书笔记之函数,this,闭包
一.函数基本理论 function compare(val1,val2){ return val1 - val2; }var result = compare(5,10); 1,函数的定义没什么意义, ...
随机推荐
- phpStrom--我常用的快捷键
ALT+ ←/→ 切换代码视图,标签切换 ALT+ ↑/↓ 在方法间快速移动定位 ctrl+shift+r 查找 替换 alt+ctrl+l 格式化代码 CTRL+N 查找类 CTRL+W ...
- 爬格子问题(经典强化学习问题) Sarsa 与 Q-Learning 的区别
SARSA v.s. Q-learning 爬格子问题,是典型的经典强化学习问题. 动作是上下左右的走,每走一步就会有一个-1的奖赏.从初始状态走到最终的状态,要走最短的路才能使奖赏最大.图中有一个悬 ...
- XDCTF2015_re100
去年做的一道 CTF,清理文档 0x01 The .init and .fini Sections 参考下面链接:http://www.ru.j-npcs.org/usoft/WWW/www_debi ...
- LBS推荐系统的设计方法
https://www.csdn.net/article/2015-12-24/2826554 http://www.datayuan.cn/article/14797.htm https://my. ...
- python sort、sorted高级排序技巧
文章转载自:脚本之家 Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列. 1)排序基础 简单的升序排序是非常容易的 ...
- 在django中进行MySQL入库
在django中进行mysql 入库 需要导入 : from django.db import models 在添加主键时,需要使用: primary_key=True id = models. ...
- MAC安装python jupyter notebook
介绍: Jupyter Notebook(此前被称为 IPython notebook)是一个交互式笔记本,支持运行 40 多种编程语言. Jupyter Notebook 的本质是一个 Web 应用 ...
- Fedora瘦身
启用的服务 systemctl list-unit-files --type=service | grep enabled 所有服务 systemctl list-unit-files --type= ...
- poj 2155 B - Matrix 二维树状数组
#include<iostream> #include<string> #include<string.h> #include<cstdio> usin ...
- 【BZOJ1492】【NOI2007】货币兑换
我果然不会斜率优化 原题: 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是 ...