javascript 闭包详解

看了一下网上闭包的概念及文章,对于这个问题,自己做一个梳理吧。

问:闭包是什么?
答:闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

这个是我自身第一次碰到闭包的问题

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8"/>
<title>闭包循环问题</title>
<style type="text/css">
p {background:#ccc; width: 300px; height: 100px;}
</style>
</head>
<body>
<p id="p0">段落0</p>
<p id="p1">段落1</p>
<p id="p2">段落2</p>
<p id="p3">段落3</p>
<p id="p4">段落4</p>
<script type="text/javascript">
for( var i=0; i<5; i++ ) {
document.getElementById("p"+i).onclick=function() {
alert(i); //访问了父函数的变量i, 闭包
};
};
</script>
</body>
</html>

如果你以前没这么用过的话,估计也会认为单击某个段落就会弹出这个段落相应的编号0,1,2,3,4。但实际上是都是弹出5;

对于这个问题网上已经有很多讨论的博客了,他们给出了很多方法去实现弹出对应的编号。

解决方法1:将变量i保存在对应的段落的某个属性上

var pAry = document.getElementsByTagName("p");
for( var i=0; i< 5; i++ ) {
pAry[i].no = i;
pAry[i].onclick = function() {
alert(this.no);
}
};

解决方法2:加一层闭包,i 以函数参数形式传递给内层函数

var pAry = document.getElementsByTagName("p");
for( var i=0; i< 5; i++ ) {
pAry[i].no = i;
pAry[i].onclick = function() {
alert(this.no);
}
};

对于这个产生的闭包问题,网上的说法是“变量i是以指针或者变量地址方式保存在函数中”;好吧,都和指针扯上关系了。。。。那就再探索一下吧。

探索1,返回的都是10而不是而是

(function test() {
var temp =10;
for(var i=0; i< 5; i++ ){
document.getElementById("p"+i).onclick=function() {
alert(temp); //访问了父函数的变量temp, 闭包
}
};
temp=20;
})();

探索2,返回一次10,接下去返回的都是20

(function test() {
var temp =10;
for( var i=0; i< 5; i++ ) {
document.getElementById("p"+i).onclick=function() {
alert(temp); //访问了父函数的变量i, 闭包
}
if(i===1){
alert(temp);
}
};
temp=20;
})();

由探索的1、2,可以得出结论:函数内部访问了与函数同级的变量,那么该变量是常驻内存的。访问该变量实质上是访问的是变量的地址;

接着,又看了一篇关于“JS闭包中的this对象”的文章,继续来讨论一下,this这个问题吧。

// js闭包this对象1
var name = 'The Window';
var object = {
  name : 'My Object',
  getNameFunc1 : function(){
    // return this.name;
    console.log(this);//object
    return function(){//闭包,访问的便是全局变量的了,this指windows
     console.log(this);//windows
     return this.name; //The Window
    }
  },
  getNameFunc2 : function(){
     return this.name;//访问的是object
  },
  aa:function(){
   alert(22);
  }
};
alert(object.getNameFunc1()());//弹出“The Window”

问: 那么为什么匿名函数没有取得其包含作用域的this对象呢?
答:每个函数在被调用时都会自动获取两个特殊变量:this 和 arguments。 内部函数在搜索这两个变量时,指挥搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量。
不过通过下面的代码可以做到这一点(直接访问外部函数中的变量):

// js闭包this对象2
var name = 'The Window';
var object = {
  name : 'My Object',
  getNameFunc : function(){
   var that = this;
   console.log(this);//输出的是object
   return function(){
    console.log(this);//输出的仍然是Windows
    return that.name;
   };
  }
};
alert(object.getNameFunc()());//弹出“My Object”

不同之处在于把this对象赋给了一个that变量,即使在函数返回之后,that也仍然引用这object,所以会返回object。
写了那么多闭包的东西,那也顺便再说一下闭包有神马用处吧;不然,一直捣乱那闭包可真是一个不好的家伙呢。

看这样一典型的闭包的例子:

function A(){
 var a=1;
 function B(){
  return a;
 };
 return B;
};

var C=A();//C取得A的子作用域B的访问接口
console.log(C());//1 C能访问到B的父级作用域中的变量a

只要其他作用域能取到子作用域的访问接口,那么其他作用域就有方法访问该子作用域父级作用域的变量了。这样的话,如果以后需要访问某个函数里面的值得时候,就大大的有用咯。

这些上面的很多代码其实也都是网上找的,我也只是把自己理解的,看的过程总结一下吧。

(0)

相关推荐

  • JavaScript中的闭包介绍

    所谓的闭包应该是指: 内部函数读取当前函数以外的变量,即创建时所处的上下文环境. 复制代码 代码如下: function hello(){     var char = "hello,world";     function print(){         console.log(char);     };     return print(); } 需要注意的是这里的print函数引用了外部hello函数的char变量,于是在这里我们能够返回一个 复制代码 代码如下: hello,

  • 深入解析JavaScript的闭包机制

    JavaScript 变量可以是局部变量或全局变量. 私有变量可以用到闭包. 全局变量 函数可以访问是有函数内部定义的变量,如: 实例 function myFunction() { var a = 4; return a * a; } 函数也可以访问函数外部定义的变量,如: 实例 var a = 4; function myFunction() { return a * a; } 后面一个实例中, a 是一个 全局 变量. 在web页面中全局变量属于 window 对象. 全局变量可应用于页面

  • javascript闭包的理解

    1.首先我们要知道变量作用域链 变量的作用域分两种:全局变量和局部变量.没有定义到任何函数中的变量为全局变量,在函数中定义的变量为局部变量,注意在函数内部定义变量时一定要使用var关键字,不带var关键字的变量为全局变量. javascript中每一段代码都有与之关联的作用域链,这个作用域链是一个对象列表或者链表,定义了这段代码"作用域"中的变量.顶层代码的作用域由全局变量组成:不包含嵌套的函数的作用域链有两个对象:一个是定义的函数参数和局部变量的对象,一个是全局变量对象:而嵌套函数的

  • 理解和运用JavaScript的闭包机制

    伟大的爱因斯坦同志说过:"如果你无法向一个 6 岁小孩解释清楚某问题,那说明你自己都没整明白".然而,当我向一个 27 岁的朋友解释什么是闭包时,却彻底失败了. 这原本是国外某哥们儿在 Stack Overflow 上对 JavaScript 闭包所提出的问题.不过既然此问题是在 Stack Overflow 提出的,当然也会有很多高手出来解答,其中有些回答确实是经典,如下面这个: 如果在一个外部函数中再定义一个内部函数,即函数嵌套函数,那么内部函数也可以访问外部函数中的变量: fun

  • Javascript闭包(Closure)详解

    下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量. var n=999; function f1(){ alert(n); } f1(); // 999 另一方面,在函数外部自然无法读取函数内的局部变量. function f1(){ var n=999; } alert(n)

  • 教你如何使用firebug调试功能了解javascript闭包和this

    对于跟我一样,自学javascript且没有其他语言学习经验的人来说,一开始的时候,javascript的调试也是一个比较大的难点,很多基础的东西都需要自己去摸索,这个过程是非常苦闷的. 想着趁机会将上面那篇闭包博文的配图用firebug再来演示一遍,也算是一点调试经验分享. 示例代码如下: 复制代码 代码如下: function fn(){ var max = 10; return function bar(x){     if (x > max) {     console.log(x);

  • javascript闭包(Closure)用法实例简析

    本文实例讲述了javascript闭包(Closure)用法.分享给大家供大家参考,具体如下: closure被翻译成"闭包",感觉这东西被包装的太学术化.下面参考书本和网上资源简单探讨一下(理解不当之处务请留意). 1.什么是闭包 官方的回答:所谓"闭包",指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 看了上面的定义,如果你不是高手,我坚信你会和我一样愤怒的质问:这tmd是人话吗? 要理解闭包,还是代码

  • 浅谈javascript中的闭包

    很长一段时间不理解闭包,后来了解了作用域,以及this相关问题才理解了闭包相关知识. 闭包(closure),也是面试题常客.简单点来说就是函数嵌套函数. 函数作为返回值: function foo () { var a = 1; return function () { a++; console.log(a); } } var aaa = foo(); aaa(); //2 aaa(); //3 其实这个代码不难理解,aaa是指向foo()返回的一个新函数,但是在这个函数里面引用了a变量,所以

  • javascript 闭包详解及简单实例应用

    JS 闭包详解及实例: 最近学习JS的基础知识,学习了闭包的知识点,有很多疑惑,这一段时间还是一直有在看闭包的相关知识理解就更深入了一点,下面说说我的理解. function fn(){ var a = 0; return function (){ return ++a; } } 如上所示,上面第一个return返回的就是一个闭包,那么本质上说闭包就是一个函数.那么返回这个函数有什么用呢? 那是因为这个函数可以调用到它外部的a这个变量.其实也就是说,return返回的是这个函数 + a这个变量

  • Javascript 闭包详解及实例代码

    Javascript 闭包 闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述,直接上干货,让你分分钟学会闭包! 1 闭包,一睹为快 在接触一个新技术的时候,我首先会做的一件事就是找它的 demo code.对于我们来说,看代码比自然语言更能理解一个事物的本质.其实,闭包无处不在,比如:jQuery.zepto的核心代码都包含在一个大的闭包中,所以

  • javascript 闭包详解

    看了一下网上闭包的概念及文章,对于这个问题,自己做一个梳理吧. 问:闭包是什么? 答:闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后. 这个是我自身第一次碰到闭包的问题 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"/> <title>闭包循环问题</title> <

  • JavaScript闭包详解

    在上一篇文章我们对预解释作了概述,在写这篇博文前打算写几个经典案例,考虑到那些案例综合性比较强,也就循序渐进的有了这篇博文,这样对于学习和深入JavaScript也更加容易入手. 序 一同事去面试,面试官问了一道题:你写一个闭包我看下?于是同事火速写出如下代码: 复制代码 代码如下: function fn(){     alert('Hello JavaScript Closure!!!');//妈蛋,E文本来就不好,找翻译才把闭包单词写出来 } fn(); 然后面试官摇摇头说道:"这怎么能叫

  • JavaScript高级之闭包详解

    目录 1. 闭包的概念 知识点的补充: 2. 闭包的作用: 3. 闭包示例 3.1 点击li,输出当前li的索引号 总结 1. 闭包的概念 来看一般函数的执行和启发: function stop() { var num = 0; console.log(num); } stop(); // 打印出来num是0 console.log(num); // 报错 函数未定义 1. 此时,函数的外部无法访问函数内部的变量 2. 函数内部定义的变量不会一直存在,随着函数的运行结束而消失 闭包的概念: 1.

  • 在Node.js中使用Javascript Generators详解

    Generators是Javascript的一种协同程序( coroutine 简称:协程)风格,是指那些可以在执行时暂停然后又恢复的函数,该函数是在functi配以星号符号形式如function* ,函数内有些特征关键词如yield 和yield*. function* generatorFn () { console.log('look ma I was suspended') } var generator = generatorFn() // [1] setTimeout(functio

  • COM组件中调用JavaScript函数详解及实例

    COM组件中调用JavaScript函数详解及实例 要求是很简单的,即有COM组件A在IE中运行,使用JavaScript(JS)调用A的方法longCalc(),该方法是一个耗时的操作,要求通知IE当前的进度.这就要求使用回调函数,设其名称为scriptCallbackFunc.实现这个技术很简单: 1 .组件方(C++) 组件A 的方法在IDL中定义: [id(2)] HRESULT longCalc([in] DOUBLE v1, [in] DOUBLE v2, [in, optional

  • python中函数总结之装饰器闭包详解

    1.前言 函数也是一个对象,从而可以增加属性,使用句点来表示属性. 如果内部函数的定义包含了在外部函数中定义的对象的引用(外部对象可以是在外部函数之外),那么内部函数被称之为闭包. 2.装饰器 装饰器就是包装原来的函数,从而在不需要修改原来代码的基础之上,可以做更多的事情. 装饰器语法如下: @deco2 @deco1 def func(arg1,arg2...): pass 这个表示了有两个装饰器的函数,那么表示的含义为:func = deco2(deco1(func)) 无参装饰器语法如下:

  • JavaScript cookie详解及简单实例应用

    JavaScript cookie详解 一.cookie基本介绍 cookie是document的对象.cookie可以使得JavaScript代码能够在用户的硬盘上持久地存储数据,并且能够获得以这种方式存储的数据.cookie还可以用于客户端脚本化. cookie数据可以自动地在Web浏览器好Web服务器之间传递. 在浏览器中可以通过navigator.cookieEnabled属性检查浏览器的cookie功能是否被激活.     二.cookie的基本属性     每个cookie都有四个可

  • 基于Python函数的作用域规则和闭包(详解)

    作用域规则 命名空间是从名称到对象的映射,Python中主要是通过字典实现的,主要有以下几个命名空间: 内置命名空间,包含一些内置函数和内置异常的名称,在Python解释器启动时创建,一直保存到解释器退出.内置命名实际上存在于一个叫__builtins__的模块中,可以通过globals()['__builtins__'].__dict__查看其中的内置函数和内置异常. 全局命名空间,在读入函数所在的模块时创建,通常情况下,模块命名空间也会一直保存到解释器退出.可以通过内置函数globals()

随机推荐