[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 ...
随机推荐
- 关于页面滚动值scrollTop在FireFox与Chrome浏览器间的兼容问题
需求 最近在做博客的目录功能,发现一个在现代浏览器间的一个bug,或是称之为差异,即页面滚动值(scrollTop)的获取与设定. 在此之前先说一下关于页面元素的坐标获取,这张图的经典性不必再提. 实 ...
- Library not found for -lPods 解决方法
使用cocoapods 经常会遇到的问题. 1. Library not found for -lPods 2. Pods was rejected as an implicit dependency ...
- 要期末了搞不了OI了额……
TAT~~~~~~期中完挂,求RP求期末逆袭
- Moqui学习之数据与资源
资源位置: 资源门面位置的字符串类似于URL的构成方式:协议,主机,可选端口和文件名.它支持标准的java URL协议(http https ftp jar file).同样也支持一些扩展的协议: c ...
- 使用GitHub进行团队合作
原文: Team Collaboration With GitHub GitHub已经成为的一切开放源码软件的基石.开发人员喜欢它,基于它进行协作,并不断通过它开发令人惊叹的项目.除了代码托管,G ...
- nginx下禁止访问robots.txt的设置方法
关于robots.txt文件:搜索引擎通过一种程序robot(又称spider),自动访问互联网上的网页并获取网页信 息.您可以在您的网站中创建一个纯文本文件robots.txt,在这个文件中声明该网 ...
- OC基础--OC内存管理原则和简单实例
ARC: 由于自己的学习视频太早,Xcode是iOS6版本,新建命令行项目后,系统会默认启动ARC机制,全程Automatic Reference Counting,简单的说,就是代码中自动加入了re ...
- SP*
1.PS1——默认提示符 root@tcx2250-14:/etc# echo $PS1\u@\h:\w\$ \u是用户名 \h是主机名 \w是当前目录的完整路径.请注意当你在主目录下的时候,如上面所 ...
- 【CodeForces 624C】Graph and String
题 题意 n个表示abc三个字符的点,所有a和b是相连的,所有b和c是相连的,所有相同的是相连的,现在给你n个点和他们之间的m条边,判断是否存在这样的字符串,存在则给出一个符合条件的. 分析 我的做法 ...
- PLSQL中配置Oracle方法
在服务器上,用PL/SQL连接Oracle数据库时,出现了一个问题,提示: Initialization error Could not load "F:\oracle\bin\oci.dl ...