`
fp_moon
  • 浏览: 981744 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

JS函数作用域和闭包

阅读更多

JS函数作用域和闭包

JS函数作用域:是通过词法来划分的作用域,而不是动态地划分作用域的,这意味着,它们在定义他的作用域里运行,而不是在执行他的作用域里运行。当定义了一个函数,当前的作用域链就保存起来,并且成为函数的内部状态的一部份。

在最顶级作用域链仅由全局对象组成,而不和词法作用域相关,然而,当定义一个嵌套的函数时,作用域链就包括外面的包含函数。这意味着嵌套函数可以访问包含函数的所有参数和局部变量。尽管当一个函数定义时作用域链就固定了,但作用域链中定义的属性还没有固定。作用域链是活的,并且函数被调用时,可以访问任何当前的绑定。

 

调用对象:JS解释器调用一个函数时,它首先将作用域设为定义函数时起作用的那个作用域链。然后再在作用域的前面添加一个新的对象,这个对象叫调用对象。

任何用var语名声明的局部变量也都定义在对应的调用对象中,局部变量,函数参数 Arguments对象都在函数内的作用域中,而且调用对象位于作用域链的前端,所以它就隐藏了作用域链更上层的任何同名属性(如果是最顶层作用域链,那就是隐藏了同名全局变量)。也就是JS函数调用时局部变量为什么会覆盖全局变量的原因。

 

作为名字空间的作用域对象:如果代码中和其它的大多数的代码一样,定义变量来存储计算的中间结果,代码用在不同和程序中,就不知道它所创寻建的变量是否将会和导入它的程序所使用的变量发生冲突, 解决的办法就是把代码放在函数中,然后调用这个函数。

如:function init(){//…} ; init();这样就在全局名字空间添加了一个属性     init。如果不想添加属性可以这样:(function(){//…}();

 

作为闭包的嵌入函数:JS把函数将要执行的代码以及执行这些代码的作用域构成一个综合体,把这个综合体叫做闭包。 所有的JS函数都是闭包的,但是只有当嵌套函数被导出到它所定义的作用域外时,这种闭包才有趣,当一个嵌套函数以这种方式使用时,它常常明确地叫做一个闭包。

 

如果在函数fn中定义了函数fn2那么当函数fn2被调用时,作用链包括三个对象:

它自己fn2的调用对象,fn的调用对象,以及全局对象。如果嵌套函数fn2是在fn中调用的那么作用链中的所有对象都能被释放,当对象从作用域链中移除后,也就没有对它的引用了,最终通过对它的垃圾收集而完结。function  fn(){  function fn2(){//…} ;  fn2();}

 

如果把对嵌套函数的引用保存到一个全局作用域中,情况就不相同了。有两种方法可以实现:

1.       把嵌套函数作为外围函数的返回值

2.       把嵌套函数存储为某个其他对象的属性

在这种情况下有一个对嵌套函数的外部引用,并且嵌套函数将它的引用保留给外围函数的调用对象。结果是,外围函数的一次特定调用的调用对象依然存在,函数的参数和局部变量的名字和值在这个时候得以维持。(简单点说就是外围函数 return后它的函数的参数和局部变量的名字和值还仍然存在)

 

注:如果一个外围函数同时存储了两个函数的引用,那么这两个嵌入的函数就共享同一个调用对象,并且,一个函数的一次调用所做出的改变对于另一个函数的调用来说也是可见的。

 

使用第一种方式闭包的例子:

 UniqueId = (function(){

  var   id  = 0;

  return function(){teturn id++;};

})();

使用第二种方式闭包的例子:(使用闭包的私有属性)

<script type="text/javascript">

         function makeProperty(o , name , predicate){

           var  value ;

           o["get" + name] = function(){ return value; };

           o["set" + name] = function(v){

             if(predicate && ! predicate(v))

                 throw "set"+name+": invalid  value" +v;

             else

                 value = v;

           };

        }

       

        var  o = {};

        makeProperty(o , "Name" , function(x){ return typeof x =="string"; })

        o.setName("jj");

        alert(o.getName());

       try{

           o.setName(0);

       }catch(e){

           alert(e);

       }

        

        </script>

分享到:
评论

相关推荐

    JS的作用域与闭包

    ### JS的作用域与闭包 #### 一、作用域的基础概念 作用域是JavaScript中一个非常核心的概念,它定义了变量的可见性和生命周期。在学习作用域之前,我们需要先了解几个基本概念: - **变量**: 在JavaScript中,...

    javascript 闭包、匿名函数、作用域链

    JavaScript中的闭包、匿名函数和作用域链是编程中至关重要的概念,它们是理解JavaScript运行机制的关键。在本文中,我们将深入探讨这三个概念,并通过实际示例来展示它们的运用。 首先,我们来讨论“闭包”。闭包是...

    第6章 JS基础-作用域和闭包【三座大山之二,不会闭包,基本不会通过】.rar

    JavaScript是前端开发中的核心语言,其作用域和闭包机制是理解JS运行原理的关键部分。在本章节中,我们将深入探讨这两个概念,帮助你攀登"三座大山"中的第二座——闭包。 首先,我们要了解JavaScript的作用域。作用...

    【JavaScript源代码】JS难点同步异步和作用域与闭包及原型和原型链详解.docx

    全局作用域的变量在整个脚本中都可访问,而函数作用域的变量只在其定义的函数内可见。ES6引入了块级作用域,使得在`{}`中的`let`和`const`声明的变量只在其所在的代码块内有效。闭包是一种特殊的作用域现象,它允许...

    原型、作用域、闭包的完整解释(一)

    在JavaScript编程语言中,原型(Prototype)、作用域(Scope)和闭包(Closure)是三个核心概念,对于理解和编写高效、可维护的代码至关重要。本文将深入探讨这三个概念,并通过实例解析它们的工作原理。 首先,...

    JavaScript作用域、闭包、对象与原型链概念及用法实例总结

    - **函数作用域**:JavaScript的变量作用域主要分为函数作用域和全局作用域。函数作用域意味着变量在其定义的函数内部有效。在函数内部定义的变量不能在函数外部访问,而函数外部定义的变量可以在函数内部访问。 -...

    深度探讨javascript函数的原型链和闭包

    `)仅在该函数作用域内可见,而外部变量(如`out_var`)则可以通过作用域链在内部访问。闭包是理解作用域链的关键概念,它允许内部函数记住其定义时的作用域,即使外部函数已经完成执行。闭包常常用于封装变量和实现...

    javascript 词法作用域和闭包分析说明

    在JavaScript中,全局作用域中声明的变量和函数可以被任何其他代码访问,而函数作用域中的变量和函数则只在函数内部可见,外部无法直接访问。 闭包是JavaScript特有的一个概念,它允许函数访问并操作函数外部的变量...

    005课-继承作用域闭包.rar

    此外,JavaScript还引入了块级作用域的概念(通过let和const关键字),以及函数作用域和词法作用域的概念。词法作用域是指函数的执行上下文由其定义时的位置决定,而不是调用时的位置。 **闭包** 闭包是JavaScript...

    JavaScript 中的闭包是指内部函数可以访问外部函数作用域中的变量

    这一特性是基于JavaScript的函数作用域规则以及函数本身可以作为值进行传递的特点所形成的。 闭包的形成依赖于以下几点: 1. **函数作用域**:在JavaScript中,变量的作用域由其声明的位置决定。如果一个变量是在...

    JS匿名函数、闭包

    ### JS匿名函数、闭包详解 #### 一、匿名函数概览 **匿名函数**,又称**拉姆达函数**...然而,需要注意的是,由于闭包会导致函数的作用域被持续保留,因此过度使用闭包可能会导致内存消耗过大,需要谨慎设计和使用。

    JavaScript中的作用域链和闭包

    执行上下文有一个自己的作用域链,这个链是在函数作用域链的基础上初始化的。 **活动对象(Active Object)**是执行上下文的一部分,它包含了函数的所有局部变量、参数和`this`。当函数执行时,活动对象被创建并推...

    浅谈JavaScript作用域和闭包

    JavaScript有两种类型的局部作用域:函数作用域和块级作用域。函数作用域是指在函数内部声明的变量只在该函数内部有效。而块级作用域则是通过使用大括号({})定义的,例如if语句、循环语句或者单独的代码块中。在...

    Web前端面试题目JavaScript(作用域,原型。原型链,闭包,封装函数).txt

    前端面试题,包含JavaScript的闭包,作用域,原型,原型链,上下文环境以及DOM,BOM封装函数深度克隆,以及一些常见的·JS问题,试题简单但是容易混淆,作为前端工程师必考题

    深入了解JS之作用域和闭包

    JavaScript中的作用域和闭包是理解JS编程的关键概念,它们涉及到变量的生命周期、作用范围以及内存管理。作用域决定了变量在哪里可被访问,而闭包则是一种特殊的作用域机制,它允许函数访问并操作在其外部定义但不在...

    javascript作用域和闭包使用详解

    作用域JavaScript 中有两种作用域:函数作用域和全局作用域。 在一个函数中声明的变量以及该函数的参数享有同一个作用域,即函数作用域。一个简单的函数作用域的例子: 代码如下:function foo() { var bar = 1; {...

    javascript中的作用域和闭包详解

    闭包的创建通常涉及嵌套函数,内层函数对外层函数作用域中变量的引用形成了闭包。在创建闭包时,需要注意内存泄漏的问题,尤其是在循环中创建闭包时,如果将外部变量的引用暴露给了全局变量,这可能会导致内存泄漏。...

    深入理解javascript作用域和闭包

    在这段代码中,`j`虽然在`if`语句内声明,但仍然在函数作用域内可见。忘记使用`var`会导致变量在全局作用域中声明,可能会导致意外的副作用。 接下来是**作用域链**。每个函数在执行时都有一个与之关联的作用域链,...

Global site tag (gtag.js) - Google Analytics