[Effective JavaScript 笔记]第15条:当心局部块函数声明笨拙的作用域
嵌套函数声明。没有标准的方法在局部块里声明函数,但可以在另一个函数的顶部嵌套函数声明。
function f(){return "global"}
function test(x){
var result=[];
function f(){return "local";}//block-local
if(x){
result.push(f());
}
result.push(f());
return result;
}
test(true);//["local","local"]
test(false);//["local"]
如果我们把函数f移动到局部块里。
function f(){return "global"}
function test(x){
var result=[];
if(x){
function f(){return "local";}//block-local
result.push(f());
}
result.push(f());
return result;
}
test(true);//?
test(false);//?
js没有块级作用域,所以内部函数f的作用域应该是整个test函数。下面的这个例子的合理猜测结果是["local","local"]和["local"]。事实上,一些js环境的确如此执行。并不是所有js环境都这样,其他一些环境在运行时根据包含函数f的块是否被执行来有条件地绑定函数f。(这使代码更难理解,而且致使性能降低)
下面为chrome控制台的执行结果:
关于这点ES标准中几乎没有定义。ES5,js标准才承认局部块函数声明的存在。官方指定函数声明只能出现在其他函数或者程序的最外层。ES5建议把在非标准环境的函数声明转变成警告或错误。
一些js实现在严格模式下将这类函数报告为错误(具有局部块函数声明的处于严格模式下的程序报告一个语法错误)。有助于检测出不可移植的代码,并为未来的标准版本给局部块函数声明指定更明智和可移植的主义开辟了一条路。
编写可移植的函数的最好方式是始终避免将函数声明置于局部块或子语句中。
如果你想写嵌套函数声明,应该将它置于其父函数的最外层,如示例1,如果需要有条件的选择函数,最好的方法是使用var声明和函数表达式来实现。
function f(){return "global";}
function test(x){
var g=f,result=[];
if(x){
g=function(){return "local";}
result.push(g());
}
result.push(g());
return result;
}
消除内部变量作用域的神秘性。无条件地作为局部变量绑定,而仅仅只有赋值语句是有条件的。
提示
始终将函数声明置于程序或被包含的函数的最外层以避免不可移植的行为
使用var声明和有条件的赋值语句替代有条件的函数声明
[Effective JavaScript 笔记]第15条:当心局部块函数声明笨拙的作用域的更多相关文章
- [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法
js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...
- [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象
js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...
- [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符
“1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- [Effective JavaScript 笔记]第66条:使用计数器来执行并行操作
第63条建议使用工具函数downloadAllAsync接收一个URL数组并下载所有文件,结果返回一个存储了文件内容的数组,每个URL对应一个字符串.downloadAllAsync并不只有清理嵌套回 ...
- [Effective JavaScript 笔记]第16条:避免使用eval创建局部变量
js中的eval函数是一个强大.灵活的工具.强大的工具容易被滥用,所以了解是值得的.(本人只用过它来处理json数据).错误使用eval函数的方式一:允许它干扰作用域.调用eval函数会将其参数作为j ...
- [Effective JavaScript 笔记]第51条:在类数组对象上复用通用的数组方法
前面有几条都讲过关于Array.prototype的标准方法.这些标准方法被设计成其他对象可复用的方法,即使这些对象并没有继承Array. arguments对象 在22条中提到的函数argument ...
- [Effective JavaScript 笔记] 第13条:使用立即调用的函数表达式创建局部作用域
function wrapElements(a){ var res=[],i,n; for(i=0,n=a.length;i<n;i++){ res[i]=function(){return a ...
- [Effective JavaScript 笔记]第63条:当心丢弃错误
管理异步编程的一个是错误处理.同步代码中只要使用try语句块包装一段代码很容易一下子处理所有的错误. try{ f(); g(); h(); } catch(e){ //这里用来下得出现的错误 } t ...
随机推荐
- Web fonts
不同类型的文件字体: Embedded OpenType (glyphicons-halflings-regular.eot) Scalable Vector Graphics (glyphicons ...
- 你会swap吗,按值传递还是按引用?
问题 1.Java到底是按值传递(Call by Value),还是按引用传递(Call by Reference)? 2.如下面的代码,为什么不能进行交换? public CallBy swap2( ...
- 推荐一个 angular 图像加载插件
推荐一个简单的 Angular 图片加载插件:vgSrc,插件根据图片资源的不同加载状态,显示不同图片,亲测兼容IE-8. 使用 推荐使用 bower 加载: bash bower install v ...
- AngularJS开发指南6:AngularJS表单详解
表单控件(input, select, textarea )是用来获取用户输入的.表单则是一组有联系的表单控件的集合. 用户能通过表单和表单控件提供验证的服务,知道自己的输入是否合法.这样能让用户交互 ...
- 设计模式之UML类图的常见关系(一)
本篇会讲解在UML类图中,常见几种关系: 泛化(Generalization),依赖(Dependency),关联(Association),聚合(Aggregation),组合(Compositio ...
- codevs1358 棋盘游戏
题目描述 Description 这个游戏在一个有10*10个格子的棋盘上进行,初始时棋子位于左上角,终点为右下角,棋盘上每个格子内有一个0到9的数字,每次棋子可以往右方或下方的相邻格子移动,求一条经 ...
- Tomcat Server Configuration Automation Reinforcement
目录 . 引言 . 黑客针对WEB Server会有那些攻击面 . 针对Tomcat Server可以做的安全加固 . Managing Security Realms with JMX . 实现对T ...
- Linux Communication Mechanism Summarize
目录 . Linux通信机制分类简介 . 控制机制 0x1: 竞态条件 0x2: 临界区 . Inter-Process Communication (IPC) mechanisms: 进程间通信机制 ...
- DLUTOJ 1209 字典序和r-子集
传送门 Time Limit: 6 Sec Memory Limit: 128 MBSubmit: 73 Solved: 14 Description Input 多组输入数据. 每组数据: 第一 ...
- ISO 基础之 (十三) protocol 协议
一 简绍 protocol,简单来说就是一系列不属于任何类的方法列表,其中声明的方法可以被任何类实现.这种模式一般称为代理(delegation)模式.通过Protocol定义各种行为,在不同的场景采 ...