`
fp_moon
  • 浏览: 970402 次
  • 性别: 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>

分享到:
评论

相关推荐

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

     目录 JS三座大山同步异步同步异步区别作用域、闭包函数作用域链块作用域闭包闭包解决用var导致下标错误的问题投票机闭包两个面试题原型、原型链原型对象原型链完整原型链图 JS三座大山 同步异步同步异步区别...

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

    嵌套作用域变量搜索规则:当在函数中引用一个变量时,JS会搜索当前函数作用域,如果没有找到则搜索其上层作用域,一直到全局作用域。 var value = 'global'; var f1 = function(){ console.log

    JS匿名函数、闭包

    在后台执行环境中,闭包的作用域链包含着它自己的作用域、包含函数的作用域和全局作用域; 通常,函数的作用域及其所有变量都会在函数执行结束后被销毁; 但是,当函数返回了一个闭包时,这个函数的作用域将会...

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

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

    javascript作用域和闭包使用详解

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

    浅谈JavaScript作用域和闭包

    作用域和闭包在JavaScript里非常重要。但是在我最初学习JavaScript的时候,却很难理解。这篇文章会用一些例子帮你理解它们。 我们先从作用域开始。 作用域 JavaScript的作用域限定了你可以访问哪些变量。有两种作用...

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

    作用域和闭包 ECMAScript5: JS 的代码没有代码块;使用函数运行的机制进行创建闭包;闭包就是作用域的意思; ES5中,JS中只有函数才可以创建能操作的作用域; JavaScript中的内存也分为栈内存和堆内存。一般来说,...

    JavaScript闭包函数

    闭包是ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包。闭包的创建相对容易,人们甚至会在...而闭包工作机制的实现很大程度上有赖于标识符(或者说对象属性)解析过程中作用域的角色。

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

    NULL 博文链接:https://xieyaxiong.iteye.com/blog/1558277

    JS页面获取 session 值,作用域和闭包学习笔记

    主要介绍了JS页面获取 session 值,作用域和闭包,结合具体实例形式分析了javascript与jsp交互获取session值、函数作用域及闭包相关操作技巧,需要的朋友可以参考下

    深入Javascript函数、递归与闭包(执行环境、变量对象与作用域链)使用详解

    本篇文章对Javascript中函数、递归与闭包(执行环境、变量对象与作用域链)的使用进行了详细的分析介绍。需要的朋友参考下

    javascript中的作用域和闭包详解

    JavaScript变量实际上只有两种作用域,全局变量和函数的内部变量。在函数内部任何一个地方定义的变量(var scope)其作用域都是整个函数体。 全局变量:指的是window对象下的对象属性。 作用域划分:基于上下文,以...

    深入理解javascript原型和闭包

    深入理解javascript原型和闭包(01)——一切都是对象 深入理解javascript原型和闭包(02)——函数和对象的关系

    JavaScript函数式编程

    全书共9章,分别介绍了JavaScript函数式编程、一等函数与Applicative编程、变量的作用域和闭包、高阶函数、由函数构建函数、递归、纯度和不变性以及更改政策、基于流的编程、类编程。除此之外,附录中还介绍了更多...

    深入理解javascript作用域和闭包

    作用域是一个变量和函数的作用范围,javascript中函数内声明的所有变量在函数体内始终是可见的,在javascript中有全局作用域和局部作用域,但是没有块级作用域,局部变量的优先级高于全局变量,通过几个示例来了解下...

    antgod#blog#3.编写函数式3-作用域与闭包1

    动态作用域在任何JS核心引擎中,都有一张全局表来存储全局变量// 动态作用域,任何JS核心引擎中,有个全局查找表const stackBinder = make

    javascript从作用域链谈闭包

    在ES 6之前,Javascript只有函数作用域的概念,没有块级作用域(但catch捕获的异常 只能在catch块中访问)的概念(IIFE可以创建局部作用域)。每个函数作用域都是封闭的,即外部是访问不到函数作用域中的变量。 ...

    JavaScript使用闭包模仿块级作用域操作示例

    正如闭包的定义一样:“闭包指的是有权访问另一个函数作用域中的变量的函数”, 闭包最大的意义就在于闭包可以对另一个函数作用域的变量进行访问,由此,闭包可以延伸出一系列的用法。 模仿块级作用域 JavaScript...

    js代码-闭包原理实例 ES5 只要函数作用域,无块级作用域

    js代码-闭包原理实例 ES5 只要函数作用域,无块级作用域

Global site tag (gtag.js) - Google Analytics