闭包机制是JavaScript的重点和难点,本文希望能帮助大家轻松的学习闭包

一、什么是闭包?

闭包就是可以访问另一个函数作用域中变量的函数
下面列举出常见的闭包实现方式,以例子讲解闭包概念

 function f1(){
   var n=;
   nAdd=function(){n+=}
   function f2(){
     alert(n);
   }
   return f2;
}
var result=f1();
result(); //
nAdd();
result(); //

二、闭包的this指针

f1是f2的父函数,而f2被赋给了一个全局变量(return的值),这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收,这便形成了闭包。
因此,可以这么理解。闭包机制就是,如果A函数引用了另一个函数B的变量,但是B返回后A仍没有返回,仍存在,因为A的引用,所以B的所有局部变量并不会随B退出而注销,会一直存在,直到A注销。此时A就是闭包。

闭包通常在全局环境调用的,所以this通常指向window,具体情况还是需要视执行环境而言,总之this指向执行环境。
若需要闭包的this指向闭包的包含对象,则需要将包含对象的this作为变量传进闭包。

三、使用闭包的注意点

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

四、解决一道闭包常见面试题

问题:

 function onMyLoad(){
/*
抛出问题:
此题的目的是想每次点击对应目标时弹出对应的数字下标 0~4,但实际是无论点击哪个目标都会弹出数字5
问题所在:
arr 中的每一项的 onclick 均为一个函数实例(Function 对象),这个函数实例也产生了一个闭包域,
这个闭包域引用了外部闭包域的变量,其 function scope 的 closure 对象有个名为 i 的引用,
外部闭包域的私有变量内容发生变化,内部闭包域得到的值自然会发生改变
*/
var arr = document.getElementsByTagName("p");
for(var i = ; i < arr.length;i++){
arr[i].onclick = function(){
alert(i);
}
}
}

解决方法
1、在外面再加一层函数,将i作为函数参数传进来,这样每次保存的是函数内部的变量,与外部i不是同一个内存空间,而每次调用函数都会生成一个局部变量,所以可以保证每次保存的值互不影响。

 for(var i = ; i<arr.length;i++){
arr[i].onclick = (function(arg){
return function () {
alert(arg);
}
})(i);
}

2、用ES6新特let,将for循环的var i改成let i,这样当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

JavaScript——闭包机制的更多相关文章

  1. Javascript闭包机制(转)

    原文地址:http://www.felixwoo.com/archives/247 参考:http://www.ruanyifeng.com/blog/2009/08/learning_javascr ...

  2. javascript 闭包内部机制

    在初学JavaScript函数式编程的时候,经常会出现令人出乎意料的结果,而原因,大都是由于不理解JavaScript闭包引起的:理解JavaScript的闭包,可以从JavaScript的闭包内部机 ...

  3. JavaScript闭包的底层运行机制

    转自:http://blog.leapoahead.com/2015/09/15/js-closure/ 我研究JavaScript闭包(closure)已经有一段时间了.我之前只是学会了如何使用它们 ...

  4. javascript 闭包(转)

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

  5. Javascript事件机制兼容性解决方案

    本文的解决方案可以用于Javascript native对象和宿主对象(dom元素),通过以下的方式来绑定和触发事件: 或者 var input = document.getElementsByTag ...

  6. javascript闭包学习例子

    javascript中的闭包个很让人头疼的概念.总结一下 闭包是指有权访问一个函数作用域中的变量的函数.创建闭包最常见的方式,是在一个函数内部创建另一个函数,用return返回出去. 使用闭包可能造成 ...

  7. JavaScript 闭包整合

    初遇闭包感觉很困惑,上网查看了些许介绍,有很多没看懂,就想先对能懂的东西整整 首先觉得要了解闭包,要先对一.JavaScript的变量作用域和作用域链有基本了解 1.变量的作用域分为:全局变量和局部变 ...

  8. 深入理解JavaScript闭包(closure)

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

  9. 对于 Javascript 闭包理解

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

随机推荐

  1. PAT A1020 Tree Traversals (25 分)——建树,层序遍历

    Suppose that all the keys in a binary tree are distinct positive integers. Given the postorder and i ...

  2. ESP32 TIMER

    ESP32有两组硬件计时器组,每组包含两个通用硬件计时器.这些计时器都是64位的可双向计数的计数器: 下面的步骤是典型的配置和操作定时器流程: 第一:初始化: 初始化定时器通过函数:timer_ini ...

  3. 完整卸载 kUbuntu-desktop from Ubuntu 14.04 LTS系统 ubuntu14.04 LTS 64Bit

    sudo apt-get remove libkde3support4 k3b-data ntrack-module-libnl-0 libkrosscore4 libgpgme++2 libqapt ...

  4. 高显卡安装 低版本的ubuntu系统导致hdmi线不能用

  5. Android Universal Image Loader java.io.FileNotFoundException: http:/xxx/lxx/xxxx.jpg

    前段时间在使用ImageLoader异步加载服务端返回的图片时总是出现 java.io.FileNotFoundException: http://xxxx/l046/10046137034b1c0d ...

  6. 『转』MySQL存储过程语法例子

    原文地址:http://blog.chinaunix.net/uid-540802-id-138873.html ------------------------- 自动生成随机数据存储过程 ---- ...

  7. HDMI传输原理:TMDS

    参考资料:http://blog.sina.com.cn/s/blog_679686370100vgg1.html: http://www.eeworld.com.cn/mndz/2011/0818/ ...

  8. 线程池(ThreadPool)

    线程池概述 由系统维护的容纳线程的容器,由CLR控制的所有AppDomain共享.线程池可用于执行任务.发送工作项.处理异步 I/O.代表其他线程等待以及处理计时器. 线程池与线程 性能:每开启一个新 ...

  9. .net mvc数据库操作添加数据的几中方法

    1. Defining sets on a derived context 1) DbSet属性:指定集合为Entity类型 2) IDbSet属性 3) 只读set属性 public IDbSet& ...

  10. MongoDB日常运维操作命令小结

    总所周知,MongoDB是一个NoSQL非数据库系统,即一个数据库可以包含多个集合(Collection),每个集合对应于关系数据库中的表:而每个集合中可以存储一组由列标识的记录,列是可以自由定义的, ...