提到闭包,想必大家都早有耳闻,下面说下我的简单理解。
平时写代码、第三方框架和组件都或多或少用到了闭包。
所以,了解闭包是非常必要的。呵呵...

一、什么是闭包
简而言之,就是能够读取其他函数内部变量的函数。
由于JS变量作用域的特性,外部不能访问内部变量,内部可以外部变量。

二、使用场景
1. 实现私有成员。
2. 保护命名空间,避免污染全局变量。
3. 缓存变量。

先看一个封装的例子:

  1. var person = function () {
  2. // 变量作用域为函数内部,外部无法访问
  3. var name = "default";
  4.  
  5. return {
  6. getName: function () {
  7. return name;
  8. },
  9. setName: function (newName) {
  10. name = newName;
  11. }
  12. }
  13. }();
  14.  
  15. console.log(person.name); // 直接访问,结果为:undefined
  16. console.log(person.getName()); // 结果为:default
  17. console.log(person.setName("langjt"));
  18. console.log(person.getName()); // 结果为:langjt

再看循环中常用闭包解决引用外部变量问题:

  1. var aLi = document.getElementsByTagName('li');
  2. for (var i=0, len=aLi.length; i<len; i++) {
  3. aLi[i].onclick = function() {
  4. alert(i); // 无论点击哪个<li>元素,弹出的值都为len,表明这里的i和在for之后打印i的值是一样的。
  5. };
  6. }

使用闭包后:

  1. var aLi = document.getElementsByTagName('li');
  2. for (var i=0, len=aLi.length; i<len; i++) {
  3. aLi[i].onclick = (function(i) {
  4. return function() {
  5. alert(i); // 此时点击<li>元素,就会弹出对应的下标了。
  6. }
  7. })(i);
  8. }

三、注意事项
1. 内存泄漏
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题。
比如:

  1. function foo() {
  2. var oDiv = document.getElementById(‘J_DIV’);
  3. var id = oDiv.id;
  4. oDiv.onclick = function() {
  5. // alert(oDiv.id); 这里存在循环引用,IE低版本页面关闭后oDiv仍在内存中。所以尽可能缓存基本类型而不是对象。
  6. alert(id);
  7. };
  8. oDiv = null;
  9. }

2. 变量命名
如果内部函数的变量和外部函数的变量名相同时,那么内部函数再也无法指向外部函数那个同名的变量。
比如:

  1. function foo(num) {
  2. return function(num) {
  3. console.log(num);
  4. }
  5. }
  6. var f = new foo(9);
  7. f(); // undefined

其实上面的用法,专业术语叫函数柯里化(Currying),就是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。本质上也利用了闭包可以缓存的特性,比如:

  1. var adder = function(num) {
  2. return function(y) {
  3. return num+y;
  4. };
  5. };
  6.  
  7. var inc = adder(1);
  8. var dec = adder(-1);
  9. //inc, dec现在是两个新的函数,作用是将传入的参数值 (+/‐)1
  10. alert(inc(99));//
  11. alert(dec(101));//100
  12. alert(adder(100)(2));//102
  13. alert(adder(2)(100));//

再比如阿里玉伯的seaJS源码中:

  1. /**
  2. * util-lang.js - The minimal language enhancement
  3. */
  4. function isType(type) {
  5. return function(obj) {
  6. return {}.toString.call(obj) == "[object " + type + "]"
  7. }
  8. }
  9.  
  10. var isObject = isType("Object");
  11. var isString = isType("String");

Javascript闭包简单理解的更多相关文章

  1. 对JavaScript闭包的理解

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 在开始了解闭包前我们必须要先理解JavaScript的变量作用域. 一.变量的作用域无非就是两 ...

  2. javascript闭包的理解

    闭包是Javascript的一个难点,但也是一个很重要的知识点. 1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部 ...

  3. 我对 javascript 闭包的理解

    学js的学到闭包,但是理解不深. 后来看了一下这篇文章: 地址:http://leepiao.blog.163.com/blog/static/4850313020112835355917/ 内容如下 ...

  4. JavaScript闭包简单应用

    闭包定义 在JavaScript中,当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包.简单说,闭包就是能够读取其他函数内部变量的函数. 闭包的作用: 1. 可以读取函数内部的变量 2. 让 ...

  5. javascript 闭包的理解(一)

    过很多谈如何理解闭包的方法,但大多数文章,都是照抄或者解释<Javascript高级程序设计(第三版)>对于闭包的讲解,甚至例程都不约而同的引用高程三181页‘闭包与变量’一节的那个“返回 ...

  6. javascript闭包的理解和实例

    所谓闭包,值得是词法表示包括不必要计算的变量的函数,也就是说,该函数可以使用函数外定义的变量. 顺便提示一下: 词法作用域:变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通 ...

  7. 关于Javascript 闭包的理解

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

  8. 关于Javascript闭包的理解

    以下内容属个人理解,如有看不明白或漏洞之处,纯属水平不佳,还望见谅. 关于闭包,高程里的定义是:指有权访问另一个函数作用域中的变量的函数.创建闭包最常见的方法就是在一个函数的内部再创建一个函数. 这里 ...

  9. python 装饰器、内部函数、闭包简单理解

    python内部函数.闭包共同之处在于都是以函数作为参数传递到函数,不同之处在于返回与调用有所区别. 1.python内部函数 python内部函数示例: def test(*args): def a ...

随机推荐

  1. -_-#【CSS3】CSS3 gradient transition with background-position

    CSS3 gradient transition with background-position <!DOCTYPE html> <html> <head> &l ...

  2. 解决weblogic Managed Server启动非常慢的情况

    jdk版本:1.7.0_79 查看控制台日志停留在如下地方: . . JAVA Memory arguments: -Xms2048m -Xmx4096m -XX:MaxPermSize=512m . ...

  3. MongoDB主从配置

    master的配置 # cat mongod.conf dbpath = /app/sinova/mongodata/db            #指定数据库目录 logpath = /app/sin ...

  4. (转载)HTML标签<br><br/>的区别在哪里?

    (转载)http://zhidao.baidu.com/question/259205863.html HTML标签<br><br/>的区别在哪里? 如果一样为什么还要分2个标 ...

  5. Linux下动态库的使用

    1.生成动态库: gcc -fPIC -shared -o libdemo.so demo.c 考虑程式库major的升级会破坏兼容性:而minior的升级则可能不会,一般建议用以下方式来生成动态库. ...

  6. (转)【C++ STL】细数C++ STL 的那些事 -- priority_queue(优先队列)

    装载自http://blog.csdn.net/tianshuai1111/article/details/7652553 一,概述 priority_queue是拥有权值观念的queue,它允许加入 ...

  7. JVM垃圾回收机制入门

    前言 数据库是大家会普遍重视的一个领域,异步通信一般用不到,虚拟机在大部分时候不会出问题,常被人忽视,所以我打算先学习虚拟机,从零单排Java高性能问题. 堆内存存储结构 Java6是以年代来规划内存 ...

  8. 最长回文 HDU 3068 (裸的Manacher)

    直接看代码: ============================================================================================= ...

  9. Servlet的一些细节(1)

    1.  Servlet程序必须映射到一个URL地址 由于客户端是通过URL访问web服务器资源,所以Servlet程序必须映射到一个URL地址.这个工作在web.xml文件中使用<servlet ...

  10. Maven deploy

      1.在maven/conf/setting.xml中: 在<servers>中加入 <server> <id>internal</id> <u ...