新手入门js闭包学习过程解析_javascript技巧

来源:脚本之家  责任编辑:小易  

function f1(){  百var n=999;    n++;  function f2(){    alert(n);  }  return f2;}var result=f1();// 执行这句后 result 实际度上是 f2// 原因是 f1() 表示执专行 f1 ,会执行到 var n=999; 和 n++; 这两句,n 为 1000// result=f1() 表示执行 f1 并把返回值保存在 result 中// 而 f1 中的返回 return f2 ,返回的是 f2// 所以执行这句后 result 实际上是引用 f2result(); // 1000// 这句实际上执行的是 f2 ,不会执行到 var n=999; 和 n++; 这两句// 在 f2 中的 alert(n) 使用了“父函数”中的局属部变量 n ,n 的值是 1000result(); // 1000// 这句与上一句相同,还是不会执行到 var n=999; 和 n++; 这两句,f1运行一次n才加1,result()是等同于f2(),然后你看你改之后的代码里面的f2函数里面有让n加1的代码么?www.zgxue.com防采集请勿采集本网。

闭包,其实是一种语言特性,它是指的是程序设计语言中,允许将函数看作对象,然后能像在对象中的操作般在函数中定义实例(局部)变量,而这些变量能在函数中保存到函数的实例对象销毁为止,其它代码块能通过某种方式获取这些实例(局部)变量的值并进行应用扩展。

js的函数可以当作像object, array之类的类型一样作为变量的值使用, 如果在一个函数里创建另外一个函数并且内部的函数使用到了外面的函数的变量那么就构成一个闭包, 这个外面的函数的变量的值会为闭包的函数一直保存直到闭包函数被内存回收掉为止

我们的理解:

我初次接触“闭包”时,看了很多资料,总是无法理解,因为一些文章写得太“学术化”,虽然措辞非常严谨,但是对初学这来说,太难理解了。 自从看到这篇文章,我的眼前“豁然开朗” 一、什么是闭包? “官方”的解释是:所谓“闭包”,指的是一个拥有许多变

其实闭包就是一个函数,一个外部函数通过调用函数并return返回出内部函数,这里的内部函数就是一个闭包;此时在内部函数中是可以访问到外部函数的变量的;

var result=[];function foo(){ var i= 0; for (;i

要想理解闭包,首先我们要了解栈堆内存和作用域链;首先我们来讲解栈堆内存:

这种情况不是闭包吧,最近刚开始看。 function a(){ var i=0; function b(){ alert(++i); } return b; } c= a(); c(); c(); 类似这种才叫闭包吧。 你这种变量不在函数体内的,不能形成闭包的吧(个人理解)。 楼主当然可以直接在函数内修改a的值,

首先我们来看个demo:

(function(){方法体})(); 说明 function(){方法体} //匿名方法 (function(){方法体})(); //后面加个()括号,直接执行匿名方法

var a=1;var obj={"name":"咸鱼"}

上面简单的两句代码,其实就是在内存中做了两件事,效果图如下:

在js简单实现深浅拷贝(https://www.zgxue.com/article/171389.htm)一文中我们知道基本数据类型是存储在栈内存中的,引用数据类型是存储在堆内存中的,其实上面的两句代码在内存中就是做了两件事:1.首先在栈内存中开辟了一块空间用来存放a的变量和值;2.在堆内存中开辟了一块空间用来存储obj的值,同时在将地址指向栈内存中的变量名obj

如果我们在代码下面再加上一句obj={"name":'张三"},这个时候我们之前存储name为咸鱼的值也就是obj原来的值会被js中的垃圾回收机制回收掉,然后obj的值重新的指向{name:"张三"}这个值;

作用域链

再来看一下这个例子:

var a = 1;function fn(){ var b = 2; function fn1(){ console.log(b);//2 console.log(a);//1 } fn1();}fn();

效果图如下:

1.var a=1;这个时候我们是在全局执行环境的,浏览器的全局环境就是window作用域,我们的window作用域中有a和fn;

2.当我们往下走到fn的时候,栈内存会开辟一块新的执行环境,此时fn的执行环境中我们有b和fn1;

3.当我们接着往下走到fn1的时候,这时栈内存同样会开辟一块新的执行环境,此时fn1的执行环境中是没有任何变量数据的,但是我们在fn1中输出a、b,我们都是可以读取到的;这是因为程序在读取变量的时候是从内到外的开始读的,是随着fn1开始往上一层一层的查找,是这样的执行顺序(fn1 = > fn = > window),如果找到window中还没有读取到变量,这时程序才会报错;

当然在执行的过程中,垃圾回收机制如果检测到程序执行完了是会进行垃圾回收的,避免造成内存泄露等问题;就是说我们的fn1里面执行完之后fn1的作用域就会被销毁,接着程序执行fn,fn执行完之后fn就会被销毁;往上执行到全局的时候,整个程序就没有了fn的作用域和fn1的作用域,只剩下浏览器的全局作用域window,这个时候window里只剩a和fn;

了解了上面的作用域链和栈内存和堆内存的知识之后,我们来开始讲解js闭包:

function outer() { var a = '123' return function add(){    //在这里因为作用域的关系,add是能访问到outer的所有变量的,但是outer是访问不到add的变量;    //所以思路一转,把add的值作为结果return出来变通实现outer外部函数访问到了内部函数变量 // add就是一个闭包函数,因为他能够访问到outer函数的作用域,add中没有找到变量a,则会继续往上层作用域找 console.log(a); }}var inner = outer() // 获得add闭包函数inner() //"123"

首先我们可以看到,在全局作用域下我们是有一个outer函数的,outer作用域里面有a和add,add作用域里面执行控制台输出a的变量,此时这里的add函数就形成了一个闭包,因为add函数里面需要访问到outer作用域下的a变量,而他们不处在同一个作用域中,所以两者相互牵引,需要输出a,上面outer中的变量a就必须得在,作用域链查找到outer的时候找到a了,输出a的时候,垃圾回收机制会认为add还没有执行完成,因为此时的作用域链查找已经到了outer作用域下,所以不会清理a的内存空间;所以这就会带来一个问题:如果我们多次的使用闭包,则会给我们的程序带来内存占用过多,导致性能问题;

函数内部能访问全局变量是javascript语言的特殊之处,但是如果我们想达到函数外部能访问内部变量的时候,我们就可以使用闭包,这就是闭包给我们带来的便利;

闭包的优缺点:

优点:

1.可以读取函数内部的变量

2.可以避免全局污染

缺点:

1.闭包会导致变量不会被垃圾回收机制所清除,会大量消耗内存;

2.不恰当的使用闭包可能会造成内存泄漏的问题;

总结:

1.作用域链查找变量的方式是一层一层的往上查找,直到找到为止,如果找到window全局作用域还未找到,就报undefined;

2.嵌套函数中,因为不在同一作用域,正常情况下内外部函数是访问不到内部函数的,但是通过闭包可以实现;

3.尽可能少的使用闭包,因为会造成内存消耗大以及有可能造成内存泄露(如果不需要的时候,不要随便使用);

需要,同往高阶的基石推荐一本书《JavaScript 高级程序设计 第三版》内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • js中的闭包实例展示
  • 通俗易懂地解释js中的闭包
  • js继承与闭包及js实现继承的三种方式
  • 利用js的闭包原理做对象封装及调用方法
  • js闭包用法实例详解
  • 深入理解javascript函数参数与闭包
  • js实现为a标签添加事件的方法(使用闭包循环)
  • 通过kettle自定义jar包供javascript使用
  • 分享9点个人认为比较重要的javascript 编程技巧
  • javascript数组快速打乱重排的方法
  • javascript接口的实现三种方式(推荐)
  • javascript验证手机号和实现星号(*)代替实例
  • 基于js实现导航条之调用网页助手小精灵的方法
  • 使用gruntjs构建web程序之构建篇
  • es6 class的应用实例分析
  • 一文读懂es7中的javascript修饰器
  • js实现登录拖拽窗口
  • js入门需要学闭包吗
  • 新手求解 javascript闭包问题
  • 初学javascript
  • js 闭包 谁能说的通俗易懂一点
  • JS 闭包主要作用是干嘛的?
  • js闭包是什么?
  • js闭包怎么写
  • js 闭包操作
  • JS中的闭包怎么用?
  • JS闭包的一些疑问
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础知识javascript类库表单特效广告代码网页特效黑客性质javascript技巧domnode.jsjs其它首页javascriptjs中的闭包实例展示通俗易懂地解释js中的闭包js继承与闭包及js实现继承的三种方式利用js的闭包原理做对象封装及调用方法js闭包用法实例详解深入理解javascript函数参数与闭包js实现为a标签添加事件的方法(使用闭包循环)通过kettle自定义jar包供javascript使用分享9点个人认为比较重要的javascript 编程技巧javascript数组快速打乱重排的方法javascript接口的实现三种方式(推荐)javascript验证手机号和实现星号(*)代替实例使用gruntjs构建web程序之构建篇es6 class的应用实例分析一文读懂es7中的javascript修饰器js实现登录拖拽窗口js刷新页面方法大全js中settimeout()的用法详解js截取字符串常用方法详细整理js页面跳转常用的几种方式js打开新窗口的2种方式js数组与字符串的相互转换方法js设置cookie、读取cookie、删除js删除数组里的某个元素方法js 将json字符串转换为json对象的javascript深入理解js闭包js中innertext/textcontent和innerhtml与jscript实现地址选择功能如何使用bootstrap 按钮实例详解javascript常见数字进制转换实例分析javascript遍历数组的三种方法map、foreajavascript检测页面是否缩放的小例子详解js树形控件—ztree使用总结javascript实现简单图片翻转的方法javascript页面添加到收藏夹的简单方法推荐4个原生javascript常用的函数
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved