javascript 函数初探 (六)--- 闭包初探#4
循环中的闭包:
让我们来看一下一个会循环三次的操作,她在每次迭代中都会创建一个返回当前序列号的新函数,该函数会被添加到一个数组中,并最终返回:
function F(){ var arr = [], i; for(i=0; i<3; i++){ arr[i] = function(){ return i; } } return arr; } var arr = F(); arr[0](); arr[1](); arr[2]();
显然这不是我们想要的结果。为啥呢?
原来我们在三次循环中创建了三个闭包,而他们最终都指向了一个共同的局部变量i。但是闭包不会记录她们的值(上文说过),她们有的只不过是相关域在创建时的一个链接(引用)。
在这个例子中,变量i恰巧存在于定义这三个函数作用域中。对于这三个函数而言,当她们要获取某个变量时,她会从其所在的域开始逐级向上找那个距离最近的i,由于循环结束时i值为3,所以这三个值同时指向了这一个i值。
如何纠正这种行为呢?答案是换一种闭包形式:
function F(){ var arr = [], i; for(i=0; i<3; i++){ arr[i] = (function(x){ return function(){ return x; } })(i); } return arr; } var arr = F(); arr[0](); arr[1](); arr[2]();
这里我们不再直接创建一个返回i的函数了,而是将i传递给了另一个即时函数,在即使函数中i就被赋值给了局部变量x,这样一来每次循环都会有不同作用域的局部变量x,那么以来每个函数中的x值都会不同了。
或者我们可以来个正常点的:
function F(){ fucntion her(x){ return function(){ return x; }; }; var arr = [], i; for(i=0; i<3; i++){ arr[i] = her(i); }; return arr; }
目的是为了使中间函数将i值本地化。
假如我们不想把一个变量暴露到全局作用域中,因为这样的话,其他代码就会有修改她们的可能,所以我们会把这个变量保护到相关函数内部,然后提供两个额外的函数, getter(),setter()。一个用来获取变量,另一个用来对变量赋值。
var gets, sets; (function(){ var a = 0; getValue = function(){ return a; } setValue = function(v){ if(typeof v === 'number'){ a = v } } })(); setValue(1); getValue();
下面一些章节我们来探讨一下对象,敬请期待。。。
javascript 函数初探 (六)--- 闭包初探#4的更多相关文章
- 深入理解javascript函数参数与闭包(一)
在看此文章,希望先阅读关于函数基础内容 函数定义与函数作用域 的章节,因为这篇文章或多或少会涉及函数基础的内容,而基础内容,我放在函数定义函数作用域 章节. 本文直接赘述函数参数与闭包,若涉及相关知识 ...
- JavaScript函数表达式、闭包、模仿块级作用域、私有变量
函数表达式是一种非常有用的技术,使用函数表达式可以无需对函数命名,从而实现动态编程.匿名函数,是一种强大的方式,一下总结了函数表达式的特点: 1.函数表达式不同于函数声明,函数声明要求有名字,但函数表 ...
- JavaScript 函数作用域和闭包
函数作用域和闭包 词法作用域 它们在定义它们的作用域里运行,而不是在执行的作用域运行,但是只有在运行时,作用域链中的属性才被 定义(调用对象),此时,可访问任何当前的绑定. 调用对象 ...
- javascript 函数表达和闭包
函数表达式和闭包 针对JS高级程序设计这本书,主要是理解概念,大部分要点源自书内.写这个主要是当个笔记加总结 存在的问题请大家多多指正! 定义函数的两种方法 函数声明: function functi ...
- javascript函数柯里化初探
// 柯里化之前 function add(x,y,z){ return x+y+z; } add(1,2,3) // 6 // 柯里化之后 function curryAdd(x){ return ...
- 剖析JavaScript函数作用域与闭包
在我们写代码写到一定阶段的时候,就会想深究一下js,javascript是一种弱类型的编程语言,而js中一个最为重要的概念就是执行环境,或者说作用域.作用域重要性体现在哪呢?首先,函数在执行时会创建作 ...
- 第八章:Javascript函数
函数是这样一段代码,它只定义一次,但可能被执行或调用任意次.你可能从诸如子例程(subroutine)或者过程(procedure)这些名字里对函数概念有所了解. javascript函数是参数化的: ...
- javascript 函数初探 (一)--- 神马是函数
神马是函数? 所谓函数,本质上是一种代码的分组形式.我们可以通过这种形式赋予某组代码一个名字,以便与之后的调用.下面,我们来示范以下函数的声明: function sum(a, b){ var c = ...
- JavaScript学习总结(二)——闭包、IIFE、apply、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
- JavaScript学习总结(三)——闭包、IIFE、原型、函数与对象
一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div, ...
随机推荐
- Cocos2d-x 3.2 学习笔记(二)创建自定义项目
一.通过命令创建项目 前面搭建好环境后,怎样创建自己的cocos2d-x项目呢? 先来看看cocos2dx 3.2的目录吧(涉及到3.1.1版本的,请自动对应3.2版本,3.x版本的环境搭建都是一样的 ...
- Dijkstra算法(一)之 C语言详解
本章介绍迪杰斯特拉算法.和以往一样,本文会先对迪杰斯特拉算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法 ...
- 【干货】如何通过OPC自定义接口来实现客户端数据的读取?
上篇博文分享了我的知识库,被好多人关注,受宠若惊.今天我把我在项目中封装的OPC自定义接口的程序分享一下.下面将会简单简单介绍下OPC DA客户端数据访问,以及搭配整个系统的运行环境. OPC(OLE ...
- iOS_UIImage_Gif的分解
/** Gif的步骤 1. 拿到Gifd的数据 2. 将Gif分解为一帧帧 3. 将单帧数据转为UIImage 4. 单帧图片保存 */ github地址: https://github.com/ma ...
- Cordova webapp实战开发:(2)认识一下Cordova
昨天写了第一篇 <Cordova webapp实战开发:(1)为什么选择 Cordova webapp?>,意料中看到大家对这个主题的兴趣,我新建的PhoneGap App开发 34819 ...
- C#获取年龄段 几零后
/// <summary> /// 根据年龄获得年龄段 /// </summary> /// <param name="age"></pa ...
- c# 游戏策划配置工具
该工具是提供策划配置excel数据,导出到mysql数据库,以及生成xml文件,和对应的xml解析实体类 实现了程序 excel 列名 ID =P 表示ID这列是唯一字段 =S=300 表示这列类型是 ...
- Logger
public static object locker = new object(); public static LogConfiguration LogConfig { set; get; } s ...
- StgCreateDocfileOnILockBytes复合文档
CRichEditCtrl 的ole技术 ------------ IRichEditOle --------------------------- 如需向CRichEditCtrl里面插入Ole对象 ...
- javascript学习笔记1-document.write
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> ...