美文网首页
谈谈js中的闭包

谈谈js中的闭包

作者: 星空下的守望2018 | 来源:发表于2018-08-03 19:09 被阅读0次

闭包的形成跟变量的作用域以及变量的生存周期密切相关

一、变量的作用域,是指变量的有效范围

当在函数中声明一个变量的时候,如果该变量前面没有带上关键字 var,这个变量就会成为全局变量 ,这当然是一种很容易造成命名冲突的做法。

另外一种情况是用 var 关键字在函数中声明变量,这时候的变量即是局部变量,只有在该函数内部才能访问到这个变量,在函数外面是访问不到的。

例:变量的搜索是从内到外而非从外到 内的

vara=1;

varfunc1 =function(){

varb=2;

varfunc2 =function(){

varc=3;

console.log ( b );// 输出:2

console.log ( a );// 输出:1

    }

    func2();

console.log(c);//输出:Uncaught ReferenceError: c is not defined

};

func1();

二、变量的生存周期

对于全局变量来说,全局变量的生存周期当然是的永久,除非我们主动销毁这个全局变量。

而对于在函数内用var关键字声明的局部变量来说,当退出函数时,这些局部变量即失去了 它们的价值,它们都会随着函数的调用的结束而销毁

例一:

varfunc =function(){

vara=1;

returnfunction(){

        a++;

console.log(a);

    }

};

varf=func();

f();// 输出:2

f();// 输出:3

f();// 输出:4

f();// 输出:5

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

例二,假设页面上有 5 个 div 节点,我们通过循环来给每个 div绑定 onclick 事件,按照索引顺序,点击第 1 个 div 时弹出 0,点击第 2 个 div 时出 1,以此类

varnodes =document.getElementsByTagName('div');

for(vari=0,len=nodes.length;i<len;i++){

nodes[ i ].onclick =function(){

        alert(i);

    }

};

测试这段代码会发现,无论点击哪个 div,最后弹出的结果都是 5

这是因为 div 节点的 onclick 事件是被异步触发的,当事件被触发的时候,for循环早已结束,此时 i 的值已经是 5,

所以在 div的 onclick 事件函数中顺着作用域链从内到外查找变量 i 时,查找到的值总是 5。

解决方法是在闭包的帮助下,每次循环的i 值都封闭起来。当在事件函数中顺着作用域链从内到外查找变量 i时,会先找到被封闭在闭包环境中的i,如果有5个div,这里的i分别 是 0,1,2,3,4

for(vari=0,len=nodes.length;i<len;i++){

(function( i ){

nodes[ i ].onclick =function(){

console.log(i);

        }

    })(i)

};

三、闭包的作用

1、封装变量—-闭包可以帮助一些不需要暴露在全局的变量封装成“私有变量”

例一,计算乘积

varmult =function(){

vara=1;

for(vari=0,l=arguments.length;i<l;i++){

a = a *arguments[i];

    }

returna;

};

2、延续局部变量的寿命

四、闭包与内存泄漏

functiona(){

vari =0;

functionb(){

console.log(++i);

    }

returnb;

}

varc = a();

c();

首先有一个封闭的函数a(即自定义的一个function a()方法),该函数内部的变量b(局部变量/局部方法)外部无法直接调用;但如果把这个函数赋值给一个全部变量c时,

全局变量c就获取到了函数局部变量b的值,从而使局部变量b的值得到了保存,即延长了一个局部变量b的生命周期,除非主动销毁这个全局变量c。

此时,我们也就制造出来了一个“闭包”。简单说“闭包是指有权限访问另一个函数作用域的变量的函数”。

在这个过程中,因为局部变量b的声明周期延长,使得Javascript的垃圾回收机制不会收回函数a所占用的资源,因为函数a的局部变量b的执行需要依赖函数a中的变量。

相关文章

  • 再谈JS闭包(JS闭包系列2)

    这篇文章,来继续谈谈Javascript闭包的剩余问题。因为在上一篇文章中关于JS闭包(JS闭包系列1)主要简单的...

  • 谈谈js中的闭包

    闭包的形成跟变量的作用域以及变量的生存周期密切相关 一、变量的作用域,是指变量的有效范围 当在函数中声明一个变量的...

  • JS闭包大结局(JS闭包系列3)

    在上一篇中再谈JS闭包(JS闭包系列2),我详细的介绍了JS中的变量作用域相关的概念,结合第一节关于JS闭包(JS...

  • 简单的聊一下闭包

    js中的闭包 闭包是学习js中永远也绕不过去的一个坎,那么,今天我们就去一段简单的代码开始聊一聊闭包 什么是闭包 ...

  • 浅谈闭包

    js中的闭包 闭包是学习js中永远也绕不过去的一个坎,那么,今天我们就去一段简单的代码开始聊一聊闭包 什么是闭包 ...

  • php之闭包函数(Closure)

    php闭包函数(Closure) JS闭包 js和php闭包使用和区别

  • 学习JavaScript闭包和作用域笔记

    JS JavaScript闭包和作用域 闭包 JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外...

  • JS闭包

    JS闭包 闭包练习

  • 2018-01-10

    js中的闭包 一.什么是闭包 闭包官方的解释是:闭包就是能够读取其他函数内部变量的函数。由于在javascr...

  • js经典题目

    1闭包 链接:学习Javascript闭包(Closure) setTimeout在js单线程中只是放在队列中并未...

网友评论

      本文标题:谈谈js中的闭包

      本文链接:https://www.haomeiwen.com/subject/slpuvftx.html