javascript闭包-讲解应用示例

来源:互联网 发布:node.js入门 编辑:程序博客网 时间:2024/06/07 06:19

javascript闭包

闭包解释:

1. 官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。2. javascript解释:Closures (闭包)是使用被作用域封闭的变量,函数,闭包等执行的一个函数的作用域。  通常我们用和其相应的函数来指代这些作用域。(可以访问独立数据的函数)3. 闭包是这样一种手段:通过它,内部函数在其父函数结束后依然能过够引用其外围函数(outer enclosing function)中的变量。4. 闭包是有权访问另一个函数作用域的变量的函数。

闭包产生:

1. 当函数可以记住并访问所在的上下文时,就产生了闭包,即使函数是在当前上下文外执行。

作用:

1.  阻止GC回收函数作用域相关变量;2.  读取修改父函数上下文内部的变量;3.  父函数内部和子函数外部连接起来的一座桥梁;4.  结合自执行匿名函数遮蔽全局变量。  

实现方式:

1. 定义父函数内部自由变量;2. 创建并且返回函数,此函数会"捕获"父函数上下文变量绑定(除了this和arguments)。  

闭包的三个事实:

1. javascript允许你引用当前函数以外定义的变量;2. 即使外部函数已经返回,当前函数任然可以引用在外部函数所定义的变量;3. 闭包可以更新外部变量的值。

闭包的应用:

1、在定时器,事件监听器、ajax请求、跨窗口通信,web workers或者其他的异步(或同步)任务中,只要使用了回调函数,实际上就是在使用闭包。2、模块暴露公共API定义3、循环和闭包:延时输出循环变量,绑定对象引用4、函数柯里化

示例:两个利用闭包来增加代码清晰度的例子

// 找到ID为main的元素var objEle = document.getElementById('main');// 更改边框样式objEle.style.border = '1px solid red';// 初始化回调函数,该函数会在1秒之后被调用setTimeout(function() {  // 隐藏对象  objEle.display = 'none';}, 1000);// 一个通用函数,显示一条延迟的警告信息function delayeAlert(msg, time) {  // 初始化内部的回调函数  setTimeout(function() {    // 使用从外部函数传入的msg    console.log(msg);  }, time);}// 调用函数delayeAlert并传入两个参数delayeAlert('Welconme', 2000);

示例:使用闭包技术的函数柯里化

// 定义一个函数,该函数生成一个新的加法函数function addGenerator(num) {  // 返回一个将两个数字相加的简单函数,其中第一个参数重该函数生成器中获取  return function(toAdd) {    return num + toAdd;  };}// addFive中包含了一个函数,该函数接受一个参数,然后将该参数与5相加并且返回计算结果var addFive = addGenerator(5);// 在这里可以看到,给函数addFive传入一个值为4的参数时,得到的结果是9console.log(addFive(4) === 9);

示例:使用匿名函数隐藏全局变量

// 创建一个匿名函数作为包装器来使用(function() {  // 这些变量通常都是作为全局变量  var msg = 'Thanks for visiting!';  // 将一个新函数绑定到全局对象  window.onload = function() {    // 使用隐藏变量    console.log(msg);  };  // 结束匿名函数定义并执行})();

示例:使用匿名函数来生成创建多个闭包函数所需要的作用域

// ID为main元素var objElement = document.getElementById('main');// 要绑定的数组var onItems = ['click', 'keypress'];// 迭代数组中的每一项for (var i = 0; i < onItems.length; i++) {  // 利用自执行的匿名函数生成作用域  (function(j) {    // 记住这一作用域中的值    // 在该作用域的每个item和j的值都是唯一的,不依赖父上下文中所创建的变量    var item = items[j];    // 为元素绑定事件函数    objElement['on' + item] = function() {      // item指向的是处于for循环上下文中的父变量      console.log('Thanks for your ' + item);    }  })(i);}

示例:模块暴露公共API定义

javascript模块模式需要两个必要条件:
1. 必须有外部的封闭函数,该函数必须至少被调用一次(每次调用都会创建一个新的模块实例)
2. 封闭函数必须返回至少一个内部函数,这样内部函数才能在私有上下文中形成闭包,并且可以访问或者修改私有的状态。

// 创建模块CoolModulefunction CoolModule() {  // 定义私有变量  var something = "cool";  var another = [1, 2, 3];  // 定义需要暴露的API方法  function doSomething() {    console.log(something);  }  function doAnother() {    console.log(another.join("!"));  }  // 暴露API  return {    DoSomething: doSomething,    DoAnother: doAnother  }}var foo = CoolModule();foo.DoSomething(); // coolfoo.DoAnother(); // 1!2!3
本文参考书籍
  1. 你不知道的JavaScript(上卷)
  2. Effective JavaScript 编写高质量JavaScript代码的68个有效方法
  3. 精通javascript(2)
  4. JavaScript函数式编程
  5. [MDN Web 文档] (https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures)
    [^footnote].[^footnote]: 第一次写内容 如有不足的地方,请大家提出来,共同进步.
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 经常熬夜皮肤不好怎么办 皮肤熬夜变暗黄怎么办 晚上上夜班白天睡不着怎么办 熬夜肾虚怎么办才能好 经常熬夜口气重怎么办 晚上睡不着白天起不来怎么办 晚上熬夜白天睡不着怎么办 在外打工孩子上学怎么办 婴儿脸干燥发红怎么办 宝宝脸上红点点怎么办 药流出血量少怎么办 药流喝药第一天发烧了怎么办 药流第一天量很少怎么办 小孩不想吃饭口臭怎么办 晚上上班白天睡不着怎么办 新车刮漆了怎么办 药流出血多怎么办 药流第二天没血怎么办 有异味怎么办%3f 养狗后悔了怎么办 买狗后悔了怎么办 小孩子不想去幼儿园怎么办 小孩子不想上幼儿园怎么办 想当兵视力不够怎么办 当兵裸眼视力差怎么办 去公司报道行李怎么办 报道第一天出糗怎么办 痛经一直想拉屎怎么办 月经第一天痛经怎么办 痛经痛得厉害怎么办 脑子里老是幻想怎么办 绿松石盘玩变黑怎么办 绿松石发乌了怎么办 泡脚泡的脚发黑怎么办 想当兵有纹身怎么办 小孩挨打不会还手怎么办 孩子挨打不敢还手怎么办 武警森林改革新兵怎么办 森林武警新兵后来怎么办 部队训练打死人怎么办? 部队受伤退伍后怎么办