文档章节

Javascript 闭包浅析

不错研究室
 不错研究室
发布于 2017/07/06 10:59
字数 960
阅读 2
收藏 0

闭包

对于Javascript程序员来说,闭包(closure)是一个难懂又必须征服的概念。闭包的形成与变量的生存周期密切相关。

变量的作用域

只有在该函数内部才能访问到这个变量,在函数外面是访问不到的。Javascript 闭包浅析(一)
变量的作用域,指变量的有效范围。我们最常谈到的是在函数中声明的变量作用域。
当在函数中声明一个变量的时候,如果该变量前面没有带上关键在var,这个变量就会成为全局变量,

这当然是一种容易造成命名冲突的做法。(ES5严格模式下报错)
另一种情况是用var关键字在函数中声明变量,这时候的变量既是局部变量,

在Javascript中,函数可以用来创造函数作用域,在函数里面可以看到外面的变量,

而在函数外面看不到函数里面的变量。因为在函数中搜索一个变量的时候,

如果该函数内并没有声明这个变量,那么此次搜索的过程会随着代码执行环境创建的

作用域链往外层逐层搜索,一直搜索到全局对象为止。变量的搜索是从内到外而非从外到内。

例:
var a = 1
var func1 = function(){
    var b = 1
    var func2 = function(){
    var c = 3
console.log(b) // 1
console.log(a) // 1
}
func2()
console.log(c) // 输出: Uncaught ReferenceError: c is not defined
}
func1()

变量的声明周期
除了变量的作用域之外,另外一个跟闭包有关的概念是变量的生存周期
对于全局变量来说,全局变量的生存周期当然是永久的,除非我们主动销毁这个全局变量。
而对于在函数内用var关键字声明的局部变量来说,当退出函数时,这些局部变量即失去了它们的价值,它们都会随着函数调用的结束而被销毁。

例:
var func = function(){
    var a = 1; // 退出函数后局部变量a将被销毁
    console.log(a)
}
func()

现在来看这段代码
var func = function(){
    var a = 1
    return function(){
    a++
    console.log(a)
}
}
var f = func()

f() //2
f() //3
f() //4
f() //5

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

闭包经典例子:
<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, len = nodes.length; i < len; i++){
    nodes[i].onclick = function(){
    console.log(i)
}
}
</script>

这段代码无论点击那个div结果都是5,这是因为div节点的onclick事件是被异步触发的,当事件被触发的时候,for循环早已经结束了,此时的i的值已经是5,当onclick事件函数中顺着作用域链从内到外查找变量i时,查找到的总是5

解决方案:
for(var i = 0, len = nodes.length; i < len; i++){
    (function(i){
        nodes[i].onclick = function(){
            console.log(i)
        }
    })(i)
}

实际应用:
var Type = {}

for(var i = 0, type; type = ['String', 'Array', 'Number'][i++];){
    (function(type){
        Type['is' + type] = function(obj){
        return Object.prototype.toString.call(obj) === '[object ' + type + ']'
        }
    })(type)
}

Type.isArray([]) // true
Type.isString('str') // true

作者:oceanden

不错研究室微信:bucuo8cuo

 

© 著作权归作者所有

上一篇: js探索框架系列
下一篇: js探索框架系列
不错研究室
粉丝 0
博文 2
码字总数 7447
作品 0
私信 提问
Javascript中闭包(closure)的理解与浅析

最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业。对于初学者来说别说理解闭包了,就连文字叙述都很难看懂。撰写此文的目的就是用最通俗的文字揭开Jav...

长平狐
2013/01/06
114
0
javascript深入理解js闭包

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

Yamazaki
2012/06/15
0
0
每个JavaScript工程师都应懂的33个概念

摘要: 基础很重要啊! 原文:33 concepts every JavaScript developer should know 译文:每个 JavaScript 工程师都应懂的33个概念 作者:stephentian Fundebug经授权转载,版权归原作者所有...

Fundebug
2018/10/30
0
0
JavaScript开发者应懂的33个概念

简介 这个项目是为了帮助开发者掌握 JavaScript 概念而创立的。它不是必备,但在未来学习(JavaScript)中,可以作为一篇指南。 本篇文章是参照 @leonardomso 创立,英文版项目地址在这里。 ...

大灰狼的小绵羊哥哥
2018/10/22
0
0
JavaScript 需要掌握的知识

1.不仅仅是面试,JavaScript 开发者都应该知道的十个概念(https://my.oschina.net/editorial-story/blog/1529543) 2. 深入理解javascript原型和闭包(完结)(http://www.cnblogs.com/wangfup...

IT追寻者
2016/06/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Python猫荐书系列之七:Python入门书籍有哪些?

本文原创并首发于公众号【Python猫】,未经授权,请勿转载。 原文地址:https://mp.weixin.qq.com/s/ArN-6mLPzPT8Zoq0Na_tsg 最近,猫哥的 Python 技术学习群里进来了几位比较特殊的同学:一...

豌豆花下猫
13分钟前
0
0
一、容器(Containers)

在容器模型中,容器大致类似于VM。他们的主要不同之处在于,每个容器不需要自己完整的操作系统。事实上,所有单个主机上的容器共享整个操作系统。这就释放了大量的系统资源,如CPU、RAM和存储...

倪伟伟
22分钟前
0
0
Guava RateLimiter限流源码解析和实例应用

在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流 缓存 缓存的目的是提升系统访问速度和增大系统处理容量 降级 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高...

算法之名
25分钟前
2
0
国产达梦数据库与MySQL的区别

背景 由于项目上的需要,把项目实现国产化,把底层的MySQL数据库替换为国产的达梦数据库,花了一周的时间研究了国产的数据库-达梦数据库,它和MySQL有一定的区别,SQL的写法也有一些区别。 ...

TSMYK
35分钟前
0
0
老也有错?35岁程序员是一道坎,横亘在每个技术职场人的心中

随着互联网的高速发展变革,大龄恐惧症越来越多地在技术圈被人讨论。很多程序员在工作5-10年以后,都会开始思考5年、10年甚至更久以后的自己,会是怎样一种生活工作状态,以及是否会被时代抛...

我最喜欢三大框架
40分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部