js 闭包深入理解与实例分析

本文实例讲述了js 闭包。分享给大家供大家参考,具体如下:

1.什么是闭包

定义:是指有权访问另一个函数作用域中的变量的函数

创建闭包:在一个函数内部创建另一个函数

基本特点 在返回的匿名函数中 可以调用外部函数的变量 如下例中所示 内部函数(匿名函数) 可以访问外部函数的变量num 形式如a[num] 原因是匿名函数作用域链中包括外部函数test1的作用域

闭包有权访问包含函数内部的所有变量 如下面的 外部函数定义变量d 在闭包中可以直接访问到d (var dd=d)

 function test1(num){
     var d;

    return function(a,b){
      var d1=a[num],d2=b[num];
      var dd=d;
 }

  }

实例参考 此时点击产品1 到 产品4 结果都是5 点击匿名函数的作用域链中包括外部函数init的活动对象 都是引用的同一个变量i 都是5 。解决办法 返回的匿名函数 通过立即执行函数 把参数i传给匿名函数

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8" />
  <title>闭包演示</title>
  <style type="text/css">
    p {background:gold;}
  </style>
  <script type="text/javascript">
    function init() {
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {
        pAry[i].onclick = function() {
          alert(i);
        }
      }
    }

  </script>
</head>
<body onload="init();">
<p>产品 0</p>
<p>产品 1</p>
<p>产品 2</p>
<p>产品 3</p>
<p>产品 4</p>
</body>
</html>

 弹出结果都是5截图 

解决办法:立即执行匿名函数 参数i是循环i的值 传递给num形参 匿名函数里 在创建闭包 可以访问这个传递过来的值num

pAry[i].onclick = function(num){//......}(i)
<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8" />
  <title>闭包演示</title>
  <style type="text/css">
    p {background:gold;}
  </style>
  <script type="text/javascript">
     /*修改后*/
     function init() {
     var pAry = document.getElementsByTagName("p");
     for( var i=0; i<pAry.length; i++ ) {
     pAry[i].onclick = function(num) {

     return function(){
     alert(num)
     }
     }(i)
     }
     }

  </script>
</head>
<body onload="init();">
<p>产品 0</p>
<p>产品 1</p>
<p>产品 2</p>
<p>产品 3</p>
<p>产品 4</p>
</body>
</html>

  结果点击第一展示

还有这样写也是可以的

 function a(){
      var pAry = document.getElementsByTagName("p");
      for( var i=0; i<pAry.length; i++ ) {
        (function(num){
          pAry[num].onclick = function() {
            alert(num);
          }
        })(i)
      }
    }

1.1 闭包的原理

-1) 闭包的作用域链 包括 闭包自身的作用域(一般返回匿名函数的作用域),外部函数的作用域(包含的外部函数),全局作用域

-2)通常,函数的作用域和所有变量都会在函数执行结束后被销毁

-3)函数返回一个闭包,这个函数的作用域会一直保存在内存中直到闭包不存在为止

使用闭包可以模仿块级作用域

-1)创建闭包并立即执行这个函数 不会再内存中留下该函数的引用

-2 )结果 函数内部的所有变量都会被立即销毁

2.什么是作用域链


执行环境:定义了变量或函数有权访问其他数据,决定它们各自的行为。

变量对象:每个执行环境都有一个与之关联的变量对象。

执行环境定义的所有变量和函数都保存在变量对象中。编写代码无法访问这个对象,解析器在处理数据时会在后台使用它。

-1)全局执行环境是最外围的一个执行环境

-2)web浏览器中,全局执行环境默认是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的

-3)某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义都随之销毁  全局执行环境直到应用程序退出--例如关闭网页或浏览器时才会被销毁

-4)每个函数都有自己的执行环境

作用域链:当代码在一个执行环境中执行时,会创建变量对象 一个作用域链

作用域链用途:保证对执行环境有权访问的所有变量和函数的有序访问

标识符解析:沿着作用域链一级一级的向上搜索标识符的过程。

函数参数也被当做变量来看待,因此访问规则与执行环境中的其它变量相同。 例子:下面函数chageColor(num){} 在闭包里tempColor(a){}里可用a[num]访问

实例解析

<script type="text/javascript">
  /*全局变量*/
  var color = 'red' ;

  function changeColor(num){
    var otherColor = 'blue',
      another =color,
     chage = changeColor();

      function tempColor(a){
         var temp = otherColor,
           temp2 = color,
           temp3 = changeColor();/*这里可以访问上层执行环境otherColor another chage 和全局color*/
         var u =a[num];

      }

  }
</script>

  全局 window

|

|-------------color 全局变量

|------------changeColor()

|

|---------------otherColor(局部变量 还有两个就是调用的上层全局环境里的color变量和函数chageColor)

|---------------tempColor()

|-------------------h(变量h不能被上层执行环境调用 只能在tempColor()里调用 标识符向上搜索沿着作用域链 这个环境里可以调用外层环境和全局环境的变量)

参考:

https://www.jb51.net/article/183094.htm

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

(0)

相关推荐

  • JavaScript中闭包的写法和作用详解

    1.什么是闭包 闭包是有权访问另一个函数作用域的变量的函数. 简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内.而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数和声明的其他内部函数.当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包. 2.变量的作用域 要理解闭包,首先要理解变量的作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变

  • 一不小心就做错的JS闭包面试题

    由工作中演变而来的面试题 这是一个我工作当中的遇到的一个问题,似乎很有趣,就当做了一道题去面试,发现几乎没人能全部答对并说出原因,遂拿出来聊一聊吧. 先看题目代码: function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n); } }; } var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,?,?,? var b = fun(0).fun(

  • 前端开发必须知道的JS之闭包及应用

    在前端开发必须知道的JS之原型和继承一文中说过下面写篇闭包,加之最近越来越发现需要加强我的闭包应用能力,所以此文不能再拖了.本文讲的是函数闭包,不涉及对象闭包(如用with实现).如果你觉得我说的有偏差,欢迎拍砖,欢迎指教.一. 闭包的理论 首先必须了解以下几个概念: 执行环境 每调用一个函数时(执行函数时),系统会为该函数创建一个封闭的局部的运行环境,即该函数的执行环境.函数总是在自己的执行环境中执行,如读写局部变量.函数参数.运行内部逻辑.创建执行环境的过程包含了创建函数的作用域,函数也是在

  • javascript深入理解js闭包

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

  • 一分钟理解js闭包

    什么是闭包? 先看一段代码: function a(){ var n = 0; function inc() { n++; console.log(n); } inc(); inc(); } a(); //控制台输出1,再输出2 简单吧.再来看一段代码: function a(){ var n = 0; this.inc = function () { n++; console.log(n); }; } var c = new a(); c.inc(); //控制台输出1 c.inc(); //

  • 详谈JavaScript 匿名函数及闭包

    1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种:这也是最常规的一种 复制代码 代码如下: function double(x){     return 2 * x;   } 第二种:这种方法使用了Function构造函数,把参数列表和函数体都作为字符串,很不方便,不建议使用. 复制代码 代码如下: var double = new Functio

  • js闭包的用途详解

    我们来看看闭包的用途.事实上,通过使用闭包,我们可以做很多事情.比如模拟面向对象的代码风格:更优雅,更简洁的表达出代码:在某些方面提升代码的执行效率. 1 匿名自执行函数 我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处, 比如:别的函数可能误用这些变量:造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的). 除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一

  • js闭包实例汇总

    Js闭包 闭包前要了解的知识 1. 函数作用域 (1).Js语言特殊之处在于函数内部可以直接读取全局变量 复制代码 代码如下: <script type="text/javascript"> var n=100; function parent(){   alert(n); } parent();//100 </script> 如果在php里 复制代码 代码如下: <?php $n=100; function parent(){   echo $n; }

  • js bind 函数 使用闭包保存执行上下文

    复制代码 代码如下: window.name = "the window object" function scopeTest() { return this.name; } // calling the function in global scope: scopeTest() // -> "the window object" var foo = { name: "the foo object!", otherScopeTest: fu

  • JavaScript闭包 懂不懂由你反正我是懂了

    越来越觉得国内没有教书育人的氛围,为了弄懂JS的闭包,我使出了我英语四级吃奶的劲去google上搜寻着有关闭包的解释,当我看到stackoverflow上这一篇解答,我脑中就出现了一句话:就是这货没跑了! 不才译文见下,见笑了. Peter Mortensen问: 就像老Albert所说的,"如果你不能向一个六岁的孩子解释清楚,那么其实你自己根本就没弄懂."好吧,我试着向一个27岁的朋友就是JS闭包(JavaScript closure)却彻底失败了. 你们会怎么把它解释给一个充满好奇

  • js闭包所用的场合以及优缺点分析

    先上段代码: //函数a function a() { var i=0; //函数b function b() { alert(++i); } return b; } //函数c var c = a(); c(); 代码特点: 1.函数b嵌套在函数a内部: 2.函数a返回函数b. 代码中函数a的内部函数b,被函数a外面的一个变量c引用的时候,这就叫创建了一个闭包.有时候函数b也可以用一个匿名函数代替来返回,即return function(){}; 优点:1.保护函数内的变量安全,加强了封装性

  • JavaScript中的作用域链和闭包

    作用域 全局作用域 局部作用域 作用域链 执行上下文 活动对象 闭包 闭包优化 JavaScript中出现了一个以前没学过的概念--闭包.何为闭包?从表面理解即封闭的包,与作用域有关.所以,说闭包以前先说说作用域. 作用域(scope) 通常来说一段程序代码中使用的变量和函数并不总是可用的,限定其可用性的范围即作用域,作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突. 全局作用域(Global Scope) 在代码中任何地方都能访问到的对象拥有全局作用域,以下几种情形拥有全局作

随机推荐