function wrapElements(a){

var res=[],i,n;

for(i=0,n=a.length;i<n;i++){

res[i]=function(){return a[i]};

}

return res;

}

var wrapped=wrapElements([10,20,30,40,50]);

var f=wrapped[0];

f();//undefined

这个可以由之前的闭包来讲,res里的每个函数都是一个闭包,它们都可以访问上一个函数的作用域内的变量,所以每个函数都可以访问到i,但这个i是for循环运行过的i,它的值应该是a.length。所以f里对应的应该就是a[a.length],这时数组已经溢出了,所以是undefined。

注意闭包存储的是其外部变量的引用而不是值。

下面这个是一种解决方法

function wrapElements(a){

var res=[],i,n;

for(i=0,n=a.length;i<n;i++){

(function(j){

res[j]=function(){return a[j]};

})(i)

}

return res;

}

var wrapped=wrapElements([10,20,30,40,50]);

var f=wrapped[0];

f();//10

这是使用立即调用的函数表达式或叫IIFE(immediately-invoked function expression)。这是一种解决js缺少块级作用域的方法

使用IIEF来创建局部作用域注意点:

  1. 代码块不能包含任何跳出块的break和continue语句。
  2. 如果代码块引用了this或特别的arguments变量,会得到错误的含义。

提示

  • 理解绑定与赋值的区别
  • 闭包通过引用而不是值捕获它们的外部变量
  • 使用立即调用的函数表达式(IIFE)来创建局部作用域
  • 当心在立即调用的函数表达式中包裹代码块可能改变其行为的情形

[Effective JavaScript 笔记] 第13条:使用立即调用的函数表达式创建局部作用域的更多相关文章

  1. [Effective JavaScript 笔记]第17条:间接调用eval函数优于直接调用

    eval函数不仅仅是一个函数.大多数函数只访问定义它们所在的作用域,而不能访问除此之外的作用域(词法作用域).eval函数具有访问调用它时的整个作用域的能力.编译器编写者首次设法优化js时,eval函 ...

  2. [Effective JavaScript 笔记]第31条:使用Object.getPrototypeOf函数而不要使用__proto__属性

    ES5引入Object.getPrototypeOf函数作为获取对象原型的标准API,但由于之前的很多js引擎使用了一个特殊的__proto__属性来达到相同的目的.但有些浏览器并不支持这个__pro ...

  3. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  4. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  5. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  6. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  7. 深入理解javascript系列(4):立即调用的函数表达式

    本文来自汤姆大叔 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行. 在详细了解这个之前,我们来谈了解一下“自执行”这个叫法,本文对这个功能的叫法 ...

  8. [JS]深入理解JavaScript系列(4):立即调用的函数表达式

    转自:汤姆大叔的博客 前言 大家学JavaScript的时候,经常遇到自执行匿名函数的代码,今天我们主要就来想想说一下自执行.在详细了解这个之前,我们来谈了解一下"自执行"这个叫法 ...

  9. [Effective JavaScript 笔记]第67条:绝不要同步地调用异步的回调函数

    设想有downloadAsync函数的一种变种,它持有一个缓存(实现为一个Dict)来避免多次下载同一个文件.在文件已经被缓存的情况下,立即调用回调函数是最优选择. var cache=new Dic ...

随机推荐

  1. MVC4/5+jquery+bootstrap样式+dataTables+linq+WCF+EF6后台和前台的框架集合!好蛋疼哦!数据库支持MYSQL 和MSSQL,oracle。集成腾讯企业邮箱收邮件同步用户SSO登陆等功能。

    花费了我好多心血,才做出来,下个项目准备用这个框架! 大家有没有做这方面的可以交流一下! 花费了我好多心血,才做出来,下个项目准备用这个框架! 大家有没有做这方面的可以交流一下! 花费了我好多心血,才 ...

  2. LINQ浅析

    在C# 3.0之前,我们对不同的数据源(数据集合.SQL 数据库.XML 文档等等)进行操作(查询.筛选.投影等等),会使用不同的操作方式. C# 3.0中提出了LINQ(Language Integ ...

  3. 深入理解C#泛型

    前面两篇文章介绍了C#泛型的基本知识和特性,下面我们看看泛型是怎么工作的,了解一下泛型内部机制. 泛型内部机制 泛型拥有类型参数,通过类型参数可以提供"参数化"的类型,事实上,泛型 ...

  4. Javascript基础系列之(二)变量

    javascript 中变量通过var关键字(variable)来声明的. var school = "beijingyizhong" 也可以通过var 关键字给变量多个值. va ...

  5. Javascript基础系列之(五)条件语句(switch语句)

    stwith语句的格式一般如下: switch (expression){ case value :statement1 break; case value2 :statement2 break; . ...

  6. java的RMI(Remote Method Invocation)

    RMI 相关知识RMI全称是Remote Method Invocation-远程方法调用,Java RMI在JDK1.1中实现的,其威力就体现在它强大的开发分布式网络应用的能力上,是纯Java的网络 ...

  7. 搭建OpenWrt开发环境(包括编译过程)

    OpenWrt是一个高度模块化.高度自动化的嵌入式linux发行版,其编译和安装过程比普通的linux发行版而言,要简单太多了.如果您是新手,您那恐惧的心大可放到肚子里,呵呵.对于新手来说最麻烦的恐怕 ...

  8. 5.9-3 用正则表达式判断字符串text是否为合法的手机号

    package zfc; public class Zfc { public static void main(String[] args) { //判断手机号格式是否合法 String text = ...

  9. poppin_xpower_ 常城

  10. 图解Android - 如何看Android的UML 图?

    如何看UML图? UML能给我们带来什么? 这是本文要寻找的答案.UML图有很多类型,我们这里只讨论最重要也最常用的两种 - 类图和时序图. 1. 类图 通过类图,我们可以很容易的了解代码架构,理清模 ...