JavaScript之闭包就是个子公司

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 --- 维基百科

一个公司会有自己的房子【一个函数有自己的作用域】。

公司会接收一些原料,进行一些处理,也会返回一些东西。【函数接收参数,进行处理,会有返回值】

外面的东西,是大家公有的,所以在公司内部也能用外面的东西。【函数内部能访问全局变量】

房子内的东西是公司自己的。只能在公司内使用,外面看不到也用不了。【局部变量是函数私有的,只能在函数内使用,外部无法访问】

公司里面可以开一些实验室,这个实验室是公司内部的,所以也可以使用公司内部的设备。【在函数A内部定义的函数B,可以访问函数A的局部变量】

一个公司完成其历史使命后,就没用了,会被拆迁,里面的私有的设备也会消失。【函数执行完后,会被GC回收,里面的局部变量也会消亡】

目前为止一切都看起来很正常,那么重点来了,如果公司最后给出的不是产品,而是把内部实验室丢出来成为另一个公司呢,会怎么样?

答案就是这个公司还是会被拆迁,但那些子公司需要用到的设备却不会被回收,因为子公司还需要。于是,这个子公司就是闭包,它在原来的公司倒闭前跑出来了,继续存活,还在原来公司的私有设备上贴了个标签说”这个设备我还要用,你把原公司的其他东西回收就好,这个不要回收掉”,于是拆迁大队GC就不会回收这个设备。

于是我们就实现了,在某公司倒闭后还能使用其设备。【在函数运行完后,还能通过某种方式访问它的局部变量,函数结束了,但局部变量还在,闭包的效果出现了】

也就是【闭包会使变量始终保存在内存中】或者说【闭包是由函数和与其相关的引用环境组合而成的实体】

注意事项

在一个公司内部创建十个子公司的时候,这些子公司只会在现有的设备上贴标签,也就是十个子公司会共享一个设备

像这样

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

结果就会输出10个10,而不是0-9。

就好比公司有个黑板i。

在黑板i写上0,然后创立一个内部的公司,让它在明天把这个黑板上写的东西发出去。

将黑板i上的0改成1,然后再创立一个内部的公司,让它在明天把这个黑板上写的东西发出去。

黑板i上的1改成2,然后再创立一个内部的公司,让它在明天把这个黑板上写的东西发出去。

……

一共创立了十个公司。

然后公司消亡了,但黑板i被留了下来,因为还有十个子公司还要用。

明天到了,十个子公司都去看黑板i,上面写了个“10”,于是他们都向外发出了 “10”。

所以怎么做呢

for(var i = 0; i < 10; i++) {
    (function(e) {
        setTimeout(function() {
            console.log(e);
        }, 1000);
    })(i);
}

这样就不同了,每个子公司都有自己的黑板“e“(当然可以把子公司的黑板也命名为i,一样能用,就是看起来比较蛋疼)。

创立的时候就把公司的黑板i上的东西抄到自己的黑板上,等待明天发布。

于是十个子公司,都有自己的黑板,黑板上分别是他们创立的时候的黑板i上的内容,即使后面黑板i的内容变化了,但已经创立的子公司不会去管,他只管自己家的黑板e。

明天到了,十个子公司都发布了自家黑板e上的内容,也就是0-9,没人再去管原来的黑板i了。

差不多就是这样,更具体可以看详解js闭包  和 mozilla的闭包教程,这是讲得比较好的两篇。

我也是才开始学JavaScript,有什么理解错的,欢迎指出。

时间: 2024-10-05 23:11:53

JavaScript之闭包就是个子公司的相关文章

javascript 关于闭包的知识点

javascript 关于闭包的认识 概念:闭包(closure)是函数对象与变量作用域链在某种形式上的关联,是一种对变量的获取机制. 所以要大致搞清三个东西:函数对象(function object).作用域链(scope chain)以及它们如何关联(combination) 首先要建立一个印象,在js中,几乎所有的东西可以看作对象,除了null和undefined.比如常用的数组对象.日期对象.正则对象等. var num = 123; // Number var arr = [1,2,3

javascript Closure 闭包

引用自 http://www.cnblogs.com/mguo/archive/2013/06/19/3143880.html /*一.变量的作用域要理解闭包,首先必须理解Javascript特殊的变量作用域.变量的作用域无非就是两种:全局变量和局部变量.Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量.*/ var n=999; function f1(){ alert(n); } f1(); // 999//另一方面,在函数外部自然无法读取函数内的局部变量. funct

JavaScript中闭包实现的私有属性的getter()和setter()方法

注意: 以下的输出都在浏览器的控制台中 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>闭包</title> </head> <body> <script type="text/javascript"> /** * 利用闭包实现 * 这个函数给对象o增加了属性存储器方法 * 方法名称为ge

javascript学习-闭包

javascript学习-闭包 1.什么是闭包 大多数书本中对闭包的定义是:“闭包是指有权访问另一个函数作用域中的变量的函数.”.这个概念过于抽象了,对初学者而言没啥帮助.好在<Javascript忍者秘籍>5.1中给了一个例子来进一步的解释了什么是闭包: var outerValue= 'ninja'; var later; function outerFunction() { var innerValue = "samurai"; function innerFunct

两个示例介绍JavaScript的闭包

JavaScript的闭包有两个用途:一个是访问函数内部的变量:另一个是让变量的值在作用域内保持不变.函数是JavaScript 中唯一有作用域的对象,因此JavaScript的闭包依赖于函数实现,下面结合两则示例对JavaScript的闭包做简单说明. 1. 访问函数内部的变量 JavaScript中没有严格意义上的类,所以我们常用函数来模拟类.我们可以像下面这样模拟一个Counter类,并在其中定义一个count私有变量: 在JavaScript中,函数可以访问其外部定义的变量,而外部不能访

JavaScript基础–闭包

JavaScript基础–闭包 理解闭包的概念对于学习JavaScript至关重要,很多新手(包括我)开始学习闭包时,都会感觉似懂非懂,之前看了一些资料,整理了闭包的一篇博客,若有疏忽与错误,希望大家多多给意见. 概述 理解闭包的概念前,建议大家先回想一下JS作用域的相关知识,如果有疑问的同学,可以参考:JavaScript基础–作用域.闭包的定义如下: Closure is when a function is able to remember and access its lexical s

javascript中闭包的工作原理

一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话通俗的来说就是:JavaScript中所有的function都是一个闭包.不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”.看下面这段代码: 1 2 3 4 5 6 7 function a() { var i = 0; function b() { ale

关于Javascript的闭包

要理解javascript的闭包 关键是弄明白三样事情 1.变量作用域 一言以蔽之  函数内部可以访问函数外部的字段  而反之不行 1 var n=999; 2 3 function f1(){ 4 alert(n); 5 } 6 7 f1(); // 999 1 function f1(){ 2 var n=999; 3 } 4 5 alert(n); // error 此处有一坑是 若在函数内声明变量不使用var关键字 相当于是声明全局变量 也就是window的变量 2.this的含义 th

javascript中闭包的原理与用法小结(转)

一.在javaScript中闭包的五种表现形式如下: 1 /** 2 * Created by admin on 2016/12/26. 3 *//* 4 //向函数对象添加属性 5 function Circle(r){ 6 this.r=r; 7 } 8 Circle.prototype.PI=3.1415926; 9 Circle.prototype.area=function(){ 10 return this.PI*this.r*this.r; 11 }; 12 var c=new C