谈谈我对JS闭包的理解

这一篇博客承接上一篇,如果大家没看上一篇,建议看看.....直通车..... 好吧,咱们一起来看看这个闭包,这次我们的重点并不是弄明白闭包是什么?而是搞清楚JS的闭包是怎么产生的。接着上一篇博客的示例:

var a = function(x){
    var b = ‘bb‘;
    var inner = function(){
        var c = ‘cc‘;
    };
    return b;
};

当a函数执行到给inner变量赋值匿名函数之后,形成下面的引用关系,直接复用上次博客的图:

从上图很容易看出,这时候inner函数对象的[[Scope]]内部属性引用着函数a在执行期的活动对象(这里包含了a函数的全部局部变量)和全局作用域。如果这时候我们把这个inner函数传递出去,如下代码:

var a = function(x){
    var b = ‘bb‘;
    var inner = function(){
        var c = ‘cc‘;
    };
    return inner ;
};

var closure = a();

这段代码意思是:执行a函数,把inner函数返回,并把它赋值给closure变量,这时候全局变量closure和inner变量引用同一个函数,大家可以运行下下面的代码:

var a = function(x){
    var b = ‘bb‘;
    var inner = function(){
        var c = ‘cc‘;
        console.log(inner === closure);
    };
    return inner ;
};

var closure = a();

closure();/*输出控制台:true*/

这段代码证实了之前所言变量closure和inner引用同一个函数对象,换句话说就是,名为inner的函数和名为closure的函数是同一个函数,closure函数的作用域链和inner函数的当然也是一样一样的,如下图:

这时候再结合上一篇博客,大家该明白了,为什么当a函数返回后,closure函数还可以使用a函数内部的局部变量了吧。

这时候还有一个问题,那就是类比其他语言时,例如C语言,当一个函数执行完毕返回后,应该释放所有这个函数执行期所占用的内存资源,当然也包含它的局部变量了,如果不这么做,不是会造成内存泄露么?JS解释器当然会释放,但是JS解释器是这样做的:当函数执行完毕后,由JS解释器的垃圾回收机制来释放内存,它的工作机制大体上是这样的:它会定期执行,判断一块被占用的内存区域是否还被可用变量所引用,如果没有,直接释放内存,如果有,那就不释放。其实我们在编写JS代码时是没有办法直接销毁对象所占用的内存空间的,内存的释放基本依赖JS的垃圾回收机制。那么有人会说delete运算符,其实delete运算符也无法销毁对象所占用的内存空间,如下示例:

var a = {k:‘占用内存‘};
var b = a;

delete a;

console.log(b);/*{k:‘占用内存‘}对象并未被释放*/

console.log(a);/*语法错误,a is not defined*/

那么delete到底做了什么呢?它销毁了a变量,这样原来变量a和b都引用{k:‘占用内存‘}对象所占的内存区域,现在销毁a后,就只有b引用这块内存区域了。如果我们再执行下一条运算:

delete b;

这时候,就没有任何可用变量引用{k:‘占用内存‘}对象所占的内存区域了,垃圾回收机制自然会识别并释放资源。

回到闭包的话题上来,如果不产生闭包的话,a函数执行完后。a函数的执行期上下文自然会被垃圾回收机制所识别释放,a函数内部的的局部变量inner函数对象也会被释放掉,这点毫无疑问,不会留下任何内存泄露的问题。但是,如果将inner函数对象作为结果返回并赋值给了closure,产生了闭包,那么这个函数对象将不会被销毁,它的内部变量[[Scope]]引用的作用域链当然也就不会被销毁。一切都这么自然而然的发生了........^_^

不过JS的闭包,如果使用不当,是很容易造成内存泄露的,但是鉴于它的好处,我们既要使用它,也要避免造成内存泄露,所以深刻的理解它很重要^_^

好吧,今天就这些。如有错误,请轻拍............

时间: 2024-10-12 14:00:55

谈谈我对JS闭包的理解的相关文章

个人对js闭包的理解

闭包算是前端面试的基础题,但我看了很多关于闭包的文章博客,但感觉很多对于闭包的理想还是有分歧的,现在网上对闭包的理解一般是两种: 有些文章认为闭包必须要返回嵌套函数中里面用到外面函数局部变量的方法才叫闭包,有两个条件:1).函数嵌套,内部函数要用到外部函数的局部变量 2).内部函数必须返回 有些文章认为只要函数嵌套内部函数用到了外部局部变量就是闭包,不要返回内部函数 我们先看看闭包的定义到底是什么,然后在来分析我在学习js的时候不同阶段对闭包的误解.在<javascript高级程序设计中>对闭

谈谈自己对js闭包,执行上下文,作用域链,活动对象AO,变量对象VO的理解

引子:关于闭包什么是闭包呢?  从定义上来看,所有的函数都可以是闭包.当一个函数在调用时,引用了不是自己作用域内定义的变量(通常称其为自由变量),则形成了闭包:闭包是代码块和创建该代码块的上下文中数据的结合. 例子:   function mytest( ){                                var test=10;          return function( ){                  test++;               alert(t

谈谈我对JS原型的理解

昨天阿里实习的第一次电面,也是我人生中的第一次电面,问了很多问题.结果还行吧,算是进入了下一轮.虽然不知道姓名,但还是要感谢面我的那个前辈.好吧,言归正传,为什么要写这篇关于原型的博文呢?因为电面时被问到了.当时有点紧张,感觉回答的很不理想,也许是自己还没有牢固的掌握吧!所以今天就写一写我对原型的理解,顺便理一下自己的思路. 首先,JS没有类继承机制,它是靠原型机制实现继承的,两种方式孰优孰劣,在此不做评判(知识量不足╮(╯▽╰)╭) 先上代码解释这一机制: var people = { nam

浅谈对Js闭包的理解

理解Js的闭包,首先让我们先看几个概念 执行环境(executive environment)每个函数都有自己的执行环境,匿名函数默认为全局环境. 作用域链(scope chain)子函数继承父函数,但是父函数不能引用子函数. 变量对象(variable object)分为全局变量对象,和局部变量对象,前者的生存在整个环境中,后者在生存在函数的执行环境下,就是说,执行函数时被创建,当函数执行完后被销毁. 怎么被销毁的啊?目前最常见的算法是当变量对象不再被引用时,便可回收内存. 但是,若是想在函数

谈谈我对JS作用域的理解

Javascript语言在设计之初,就将函数设计成一种包含可执行代码逻辑的特殊对象.作为对象,函数可以像普通对象变量一样拥有可以编程读写的属性,也可以像普通变量一样传递.被引用.但是问题也来了,当函数执行时,解释器如何对代码内部的标示符进行解析呢?JS是这样做的,当函数对象被创建时,或者说函数被定义时,函数对象内部不仅包含了代码逻辑,还定义了一个内部属性[[Scope]]引用了一条作用域链(可以理解成为一个对象列表).如果这个函数在全局环境下被定义,那这个作用域链里就只有全局作用域. 这样说比较

js闭包的理解

闭包的两个特点: 1.作为一个函数变量的一个引用 , 当函数返回时,其处于激活状态. 2.一个闭包就是当一个函数返回时,一个没有释放资源的栈区. 其实上面两点可以合成一点,就是闭包函数返回时,该函数内部变量处于激活状态,函数所在栈区依然保留. 我们所熟知的主流语言,像C,java等,在函数内部只要执行了return,函数就会返回结果,然后内存中删除该函数所在的区域.生命周期也就停止了.一般的js函数也是这样. 但是有闭包特性的js函数有点特殊. 就例子来说: function a(){ var

js闭包的理解与用法

js回收机制:当一个函数全部执行完毕或者返回了值的时候,函数里面的变量会被清除回归到初始状态. 在某种情况: js这样的回收机制就会引出一个问题,当一个函数被执行完毕后cg了,然而在函数外的一个变量需要用调用该函数里面的值时就不能有想要的效果了 例子: 分析 for循环第一次 i 等于0的时候,传递给result的值是0,但是第二次执行时候result被cg了,i没记住值0,i直接变1了,下一次也一样. 1 var result=[]; 2 function foo(){ 3 var i= 0;

js闭包浅了解

js闭包浅理解 要理解闭包,得先知道js的变量作用域,在js中,有两种变量作用域: 全局作用域 局部作用域 一.在函数内可以访问全局变量 比如,下面的例子: <!--lang:js--> <script> var n = 100; function f1(){ console.log(n); } f1()//返回100 </script> 上面的例子很简单,下面是另一种情况. 二.在函数外无法读取函数内的局部变量 还是一个小例子: <!--lang:js-->

javascript深入理解js闭包

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