你是不是在不知不觉间创建了闭包呢?

有时候我们会在不知不觉间创建出闭包,给我们打来不必要的麻烦。比如这一个经典的例子:

我们希望能把0-9这10个数字打印出来,但实际上每个函数都返回10.

对这一段代码的运行结果高程上是这么解释的:

“因为每个函数的作用域链都保存着其父函数(在这里就是Nico函数)的活动对象(每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中,在函数作用域中,也把变量对象称为活动对象),所以它们引用的都是同一个变量 i 。当父函数数返回后,变量 i 的值是10,此时每个函数引用的都是同一个变量对象,所以在每个函数内部 i 的值都是10.”

通俗点说就是:Nico函数的变量对象只有一个,所以for循环copy出来的10个子函数都只能引用同一个变量对象,而 i 值是被定义在变量对象中的,所以当 i 值更新为10之后,因为引用的同一个变量对象也相当于引用着同一个 i ,所以这10个函数最后都会返回10.

但是这样的解释实在有点过于理论了,所以我自己的理解是这样的:

“因为嵌套函数并没有被立即执行,所以循环10次之后只是保存10

个这样的函数 function(){ return i; },调用Nico函数把这10个

函数保存在数组中,在最后循环数组输出的时候再返回 i 值,但是

那时候for循环已经结束了,i 为10,所以执行结果便是弹出10个10;”

改写一下代码证明一下我的思路:

每循环一次我让匿名函数立即执行并返回一个对应的 i 值存在niconico变量当中,

这是执行结果

结果证明我的理解并没有错,我每一次循环都会立即把对应的 i 值返回出来,因为 i 是一直在变化的,如果等到循环结束才调用的话,到那个时候 i 的值已经是10了,照这种思路其实还可以这样写:我每一次循环并不立即执行返回相应 i 值,但是每一次循环我都把当时的 i 的值储存在对应的函数当中,等循环结束再调用的时候,每一个也都能返回正确的 i 的值。talk is cheap,show you the code:

上面代码执行结果也是一样的。

好的这就结束了,纰漏之处还请各路高手们不吝赐教。

时间: 2024-11-02 11:12:39

你是不是在不知不觉间创建了闭包呢?的相关文章

探索c#之函数创建和闭包

阅读目录: 动态创建函数 匿名函数不足之处 理解c#中的闭包 闭包的优点 动态创建函数 大多数同学,都或多或少的使用过.回顾下c#中动态创建函数的进化: C# 1.0中: public delegate string DynamicFunction(string name); public static DynamicFunction GetDynamicFunction() { return GetName; } static string GetName(string name) { ret

【淡墨Unity3D Shader计划】一间 创建一个游戏场景 & 第一Shader写作

本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 邮箱: [email protected] 作为一个系统介绍Unity3D中Shader编写的系列文章的开篇.本文的第一部分为系列文章的前言,然后第二部分介绍了这个系列文章中我们会使用的游戏场景创建方式.最后一部分解说了怎样在U

无意间创建的一个闭包,以及解决办法

闭包的本质是作用域链,我们在工作中经常无意间就会创建一个闭包,比如: <input type="button" id="id1" value="1"></input> <input type="button" id="id2" value="2"></input> <input type="button" id=&

PHP中的闭包详解

PHP闭包(Closure)使用详解 作者: 字体:[增加 减小] 类型:转载 时间:2013-05-02我要评论 本篇文章介绍了,PHP闭包(Closure)的使用介绍,需要的朋友参考下 不知不觉发现PHP已经出到了5.5版本,而自己一直在用PHP5.2,让我看起来像深山出来的小伙子一样,又土又落后.在我习惯在javascript中使用闭包之后,忽然间对PHP的闭包打起了兴趣. 于是乎在网上下了个WAMP集成开发环境,是PHP5.3版本的(PHP5.3开始引入了闭包的特性),不得不说WAMP安

进击的雨燕-------------闭包

闭包是自包含的函数代码块,可以在代码中被传递和使用.Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数比较相似. 闭包可以捕获和存储其所在上下文中任意常量和变量的引用.这就是所谓的闭合并包裹着这些常量和变量,俗称闭包.Swift 会为您管理在捕获过程中涉及到的所有内存操作. 注意如果您不熟悉捕获(capturing)这个概念也不用担心,您可以在值捕获章节对其进行详细了解. 在函数章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采

深入理解javascript闭包【整理】

原文链接:http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html 英文原文:http://www.jibbering.com/faq/faq_notes/closures.html 要成为高级 JavaScript 程序员,就必须理解闭包. 本文结合 ECMA 262 规范详解了闭包的内部工作机制,让 JavaScript 编程人员对闭包的理解从"嵌套的函数"深入到"标识符解析.执行

JavaScript学习总结(二)——闭包、IIFE、apply、函数与对象

目录 一.闭包(Closure) 1.1.闭包相关的问题 1.2.理解闭包 二.对象 2.1.对象常量(字面量) 2.2.取值 2.3.枚举(遍历) 2.4.更新与添加 2.5.对象的原型 2.6.删除 2.7.封装 三.函数 3.1.参数对象 (arguments) 3.2.构造函数 3.3.函数调用 3.3.1.call 3.3.2.apply 3.3.3.caller 3.3.4.Callee 3.5.立即执行函数表达式 (IIFE) 3.5.1.匿名函数与匿名对象 3.5.2.函数与函数

js闭包简要分析

相信大多数接触过js编程的程序员或多或少都对js中的闭包了解一些吧,所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包是 ECMAScript (JavaScript)最强大的特性之一,但用好闭包的前提是必须理解闭包.闭包的创建相对容易,人们甚至会在不经意间创建闭包,但这些无意创建的闭包却存在潜在的危害,尤其是在比较常见的浏览器环境下.如果想要扬长避短地使用闭包这一特性,则必须了解它们的工作机制.而闭包工作机制的实现很大程

浅析闭包和内存泄露的问题

JavaScript使用一种称为垃圾收集的技术来管理分配给它的内存.这与C这样的底层语言不同,C要求使用多少借多少,用完再释放回去.其他语言,比如 Objective-C,实现了一个引用计数系统来辅助完成这些工作,我们能够了解到有多少个程序块使用了一个特定的内存段,因而可以在不需要时清除这些内存段. JavaScript是一种高级语言,它一般是通过后台来维护这种计数系统. 当JavaScript代码生成一个新的内存驻留项时(比如一个对象或函数),系统就会为这个项留出一块内存空间.因为这个对象可能