那些年,我们误解的 JavaScript 闭包

说到闭包,大部分的初始者,都是谈虎色变的。最近对闭包,有了自己的理解,就感觉。其实我们误解闭包。也被网上各种说的闭包的解释给搞迷糊。

一句话:要想理解一个东西还是看权威的东西。

下面我来通俗的讲解一个闭包的知识。(建议大家去读JavaScript权威指南)

我们先弄明白几个问题:

1、作为命名空间的函数:

在函数中声明的变量在整个函数体内都是可见(包括嵌套的函数)在函数的外部不是可见的。不在任何函数内声明的是全局变量

===》也就是说:一个函数它就是一个作用域,不管你里面有什么东西。他们都是一家子。

function fn(){

  var b1,b2.....;

  function a1(){}

  function a2(){}

  ..........//不管你是有多少函数,多少变量。你们都被fn用{}包围着,那么你们在fn下都是相互透明的。

}

2、函数只有在调用的时候,才会执行,函数名是函数的引用。(说白了就是在函数名的后面加个括号呗)

 function fn(){

    alert("调用我,我才会alert")

  }

fn()//在函数名的后面加了一个()这个函数才会执行。===============这点大家肯定很明白的吧

3、函数本身也是一个对象:(JavaScript中一切皆是对象,{个别的特例,咱暂且不说})

  对象:可以有属性 、方法。对象的内的方法调用自己的属性,=============这个大家也肯定没有问题吧

  也就是说,一个对象的内部是一家族。

  var obj ={

  var name;

  function getName(){}// getName() 方法和name属性,都是在obj这个对象的作用域内的==========其实就是上面1所称述的那样。

}

  

好了,如果你理解,上面这三个知识点,你可以继续看下面的了。【问问自己理解这三个知识点没????????????????????】

闭包

JavaScript权威指南中有一段关于闭包的话。

函数的执行依赖于变量的作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。

总结:函数体内的变量都可以保存在这个函数的的作用域内。这种特性在计算机科学内叫做闭包

这是一个很正常的东西啊。一个函数圈了一个作用域,然后一些代码,在我的区域里面保存了。不就是我的作用域下的吗?

就像:

  function a(){

    function b(){}

}

不要告诉,现在的b是属于 外人的。就像上文1说的那样,a这个函数是一个命名空间,一个作用域。在我的作用域里面的东西,怎么可能是别人的额。

===所以:在我作用域里面的,是我家的,可以拿我家的东西。(函数体内可以保存变量在这个函数的作用域。之所以说官方强调闭包,就是因为JavaScript函数内保存变量时,和其他语言,Java。。不太一样,有个作用域链等等。。。。不先管他们。)

======总之======【我们就理解为:闭包的特性的初衷就是在一个函数作用域内保存变量。一个狠狠正常的事情啊,我家的东西放我家啊,我爱我家】

例子:村子与张三家族的关系。

var area ="这是村里的东西";

function zhangjia(){
  var area ="这是张家的东西";
  function getArea(){
  return area;
  }
  return getArea();
}

zhangjia();            //这是张家的东西

如果我这样的话;

var area ="这是村里的东西";

function zhangjia(){
  var area ="这是张家的东西";
  function getArea(){
  return area;
  }
  return getArea;
}

var  getSomeArea = zhangjia();//返回的函数的引用,将此引用赋给一个变量,那么getSomeArea这个变量同样是引用张家的getArea方法啊。

getSomeArea();     //现在,调用这个方法(加())不就是调用张家的那个getArea吗。拿到的area还是张家的area啊。因为,在一个开始的时候,人家就是属于张家的,当然取张家的东西。

===============【函数的执行依赖于变量的作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。】多好的理解,很正常的逻辑啊

但是但是,要说但是了,正式由于JavaScript闭包存储变量的特殊性,就会出现一些问题。

接着看:我们看看这个经常被网上的大神拿来用的一个例子。

var result=[];
function foo(){
  var i= 0;
  for (;i<3;i=i+1){
    result[i]=function(){
    alert(i)
    }
  }
};
foo();//foo是一个函数的引用,foo()就是调用这个函数,没有问题吧。
result[0](); // 3
result[1](); // 3
result[2](); // 3

为啥,为啥,为啥都是3 。

我们期望的是每次都把对应的i值alert出来。但是结果却是这样。

来:一个函数只要在调用的时候,才会执行。(熟悉不??????)

result[i] = function(){alert(i)} 这不就是把一个函数赋值给一个变量,这个变量装的是函数的引用,注意---就是引用,就像上面说的没有执行呢。

当我们执行的时候:

result[0]() -------发生 了什么?????????????????????????????????

????????????????

对啊,就是那个闭包的问题啊;方法会去自己家里拿i值。哪个家?????foo这个家里啊。这是时候的i是3 了。alert(i)不就是3了。

多么多么正常的正常的事 啊。狠狠正常的逻辑

解决呢??

有人说,既然你说没有执行,那我就立即执行,循环的时候就执行,不光是一个引用在那里。。。

。。。。好,聪明

var result=[];
function foo(){
  var i= 0;
  for (;i<3;i=i+1){
    result[i]=(function(){
      alert(i);
    })();//立即执行,返回的是一个结果给result ,不是引用了。
  }
};
foo();

如果还想要result[i]()这种方式调用,咋办呢?

这个家族里的东西,你在拿到你的小家里去吧。在你家保存下

var result=[];
function foo(){
    var i= 0;
    for (;i<3;i=i+1){
      result[i]=(function(j){
        return function(){
        alert(j)
        }
      })(i);//作为一个参数传到小家去,虽然现在result[i]还是一个引用,引用一个函数,但是这个函数保存了每次循环时的对应的i值。
  }
};
foo();

result[1] //1

综上所述:

  闭包本来就是一个很正常的逻辑。但是由于他的实现方式涉及作用域链,作用域之间的引用问题,显得他很难理解。

  希望带着我说的额这些,多去理解一下。你发现,人家本来就是一个很正常的逻辑问题:我爱我家啊。。。。。。。。。。。

时间: 2024-10-14 16:58:48

那些年,我们误解的 JavaScript 闭包的相关文章

深入理解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

javascript闭包详解(内容为转载的,觉得不错就分享一下)

一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. Js代码 var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. Js代码 function f1(){ var n=999; } alert(n); // error 这里有一个地方需要注意,函数

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

转自:http://www.cnblogs.com/yunfeifei/p/4019504.html 好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一些实用的东西,主要将闭包的写法.用法和用途. 一.什么是闭包和闭包的几种写法和用法                                                       1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑