JavaScript闭包探究

1.什么是闭包?

W3C:闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量

要较好理解闭包,除了形式本身,还应先理解:

JS没有块级作用域:见JavaScript作用域

JS的内存回收机制:引用计数。

2.闭包的例

闭包是一种结构,getName引用了外部变量name,形成闭包。第9行把name赋给变量whoname,使name在内存中保持。如果没有getName形成闭包,People函数执行完,其name变量就被释放。

1 function People(){
2      var name = ‘xiaohua‘;
3      function getName(){
4           return name;
5      }
6      return getName;
7 }
8
9 var whoName = new People();

3.闭包容易引起的bug

var result = [];
function foo(){
    var i = 0;
    for(;i<3;i++){
         result[i] = function(){
              alert(i);
         }
    }
}

foo();

result[0](); //3
result[1](); //3
result[2](); //3 

这是因为i始终存在,没有块级作用域,i最后等于3,result数组中的所有函数里的i都指向那个等于3的i。

解决办法是给函数传参数:

1 result[i] = function(num){
2       alert(num);
3 }

这种做法的原理涉及到作用域链。作用域链依次指向由近到远的作用域对象,上面给匿名函数添加一个参数,其最近作用域对象上就会有这个参数,参数是值类型,传递的只是副本,因此解决了上述问题。

4.闭包的几个用途

  • 隔离作用域

JS虽然没有块级作用域,但是有函数作用域。为了使变量之间不会有命名冲突,使用立即执行函数把作用域隔离。下面的两个作用域内的name互不影响,无意间形成了闭包的结构。如果没有隔离作用域

 1             (function(){
 2                 var name = ‘aa‘;
 3
 4                 function a(){
 5                     return name;
 6                 }
 7             })();
 8
 9             (function(){
10                 var name = ‘bb‘;
11
12                 function a(){
13                     return name;
14                 }
15             })();
  • 作计数器
 1             var counter = function(){
 2                 var count = 0;
 3                 return function(){
 4                     return ++count;
 5                 };
 6             };
 7
 8             var countAdd = counter(); // function(){ return ++count; };
 9             countAdd();           //1
10             countAdd();           //2
11             alert(countAdd());    //3
  • 声明私有变量

JS本身没有私有变量、公共变量,静态变量的,都是模拟实现。下面如果把name作为People的属性,就无法实现私有。

 1 var People = (function(){
 2      var name = "xiaohua";
 3      function People(){};
 4      People.prototype = {
 5            getName:function(){
 6                  return name;
 7            },
 8             setName:function(newName){
 9                  name=newName;
10            }
11      };
12      return People;
13 })();
14
15 var p = new People();

5.闭包的代价

闭包引用外部变量使得外部变量在其作用域执行完毕后不能立即销毁,必须等到闭包函数被销毁,引用清楚之后才能销毁。因此,闭包最明显的代价是占用内存。

其次,复杂闭包容易造成逻辑混乱,进而导致循环引用。循环引用的结果是变量始终被引用,无法释放,造成内存泄漏。

参考:

W3C和饥人谷公开课

闭包详解

时间: 2024-11-25 15:47:49

JavaScript闭包探究的相关文章

JavaScript Oriented[探究面向对象的JavaScript高级语言特性]

JavaScript Oriented 探究面向对象的JavaScript高级语言特性 Prologue . JavaScript Introduce 1.  JS Abstract JavaScript是由Netscape公司工程师Brendan Eich研发的脚本语言,经过推广和流行,兼容ECMA-262标准,至今用于描述HTML网页行为.(前端验证,检测,响应,触发,控制等动态行为) Knowledge Tree 2.     About Document 本文涉及到的概念有JavaScr

Javascript闭包的一些研究

原文:Javascript闭包的一些研究 本文不谈闭包的概念,因为概念容易把人搞晕,本文希望通过几个鲜活的例子来探究闭包的性质,相信对理解闭包会有所帮助. 程序1 var f = (function() { var n = 10; return function() { ++n; console.log(n); } })(); f(); 输出: 11 结论: 闭包函数可以访问外层函数中的变量. 程序2 var arr = []; (function() { var n = 0; for (var

深入理解javascript闭包

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function

JavaScript 闭包

1.词法作用域: 简单地说子集能访问父级的变量, 说人话就是变量拿来就用不用传入 2.函数局部变量: 在函数体中以var 声明变量的为局部变量 + 函数传入的参数, 直接写变量名声明的变量是全局变量 3.局部变量生存期: 局部变量在函数函数的执行期间可用,  一旦执行过后,局部变量将不再可用 4.延长局部变量生存期: 现在问题来了,我想要延长局部变量的生存期,怎么办.(因为调用函数不仅仅是为了return, 有时候还需要保存函数中的状态, 或者实现类等等) 5.使用全局变量不好吗: 不好.有时函

javascript—闭包

javascript 闭包就是在另一个作用域中保存了一份它从上一级函数或作用域取得的变量(键值对0), 而这些键值对是不会随上一级函数的执行完成而销毁. function a(){ var i=0; function b(){ alert(++i); } return b; } var c=a(); c(); 在执行完var c=a()后,变量c实际上是指向了函数b,b中用到了变量i, 再执行c()后就会弹出一个窗口显示i的值(第一次为1).这段代码其实就创建了一个闭包. 为什么?因为函数a外的

JavaScript 闭包究竟是什么

JavaScript 闭包究竟是什么 1.简单的例子 首先从一个经典错误谈起,页面上有若干个div, 我们想给它们绑定一个onclick方法,于是有了下面的代码 <div id="divTest"> <span>0</span> <span>1</span> <span>2</span> <span>3</span> </div> <div id="d

全面理解Javascript闭包和闭包的几种写法及用途

一.什么是闭包和闭包的几种写法和用法                                                       1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点: 1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态. 2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区. 简单的说,Javascript允许使用内部函数---即函数定义和函数表

javascript闭包的简单理解

奖Javascript闭包前,先给大家讲个小故事 故事背景:刘备和曹操煮酒的时间段,故事可能有点小差异,刘备为曹操手下,关羽为间谍. 咳咳 曹操很想知道手下新来的刘备整天鼓捣啥: 曹操就问刘备,玄德你整天鼓捣啥: 刘备想,我靠这怎么能告诉你,劳资岂不是找死,打个马虎眼就过去了,曹操什么也没问出来: 刘备回到家里,跟关羽说,二弟,哼,曹操那个傻吊,哼! 关羽晚上也回到家里,跟老婆说,哼,大哥那个傻吊,哼!我这就去告诉丞相: 曹操也不能罢休,就去问关羽,关羽正要去告密,就一五一十  ¥%…@?%%:

javascript 闭包学习

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function