JavaScript.The.Good.Parts阅读笔记(二)作用域&闭包&减缓全局空间污染


Posted in Javascript onNovember 16, 2010

如代码块

if (true) { 
int i = 100; 
} 
print(i); //错误,变量i没有声明

如上面例子所示,代码块外的函数是无法访问i变量的。
但在javaScript里,情况则完全不同。
if (true) { 
var i = 100; 
} 
alert(i); //弹出框并显示100

很多现代语言都推荐尽可能迟地声明变量,但在Javascript里这是一个最糟糕的建议。由于缺少块级作用域,最好在函数体的顶部声明函数中可能用到的所有变量。

闭包特性:
虽然缺少块级作用域,但是函数的作用域还是存在的。
这种作用域有一个好处,就是内部函数可以访问定义它们的外部函数的参数和变量(除了this和argument)。
利用这种特性,则可以这样来设计代码。

var bankAccount = function () { 
var value = 0; 
return { 
deposit: function (inc) { 
value += inc; 
}, 
getValue: function (){ 
return value; 
} 
} 
} 

var myAccount = bankAccount(); //新开一个银行账户 
myAccount.deposit(1000); //存1000块进去 
alert(myAccount.getValue()); //should alert(1000);

value由于在bankAccount这个function里,外部无法对它进行直接操作,必须通过bankAccount function给他返回的对象来进行操作,通过这样来实现C#和java里的private的字段。

减缓全局变量污染全局空间:利用函数的作用域,我们在写js库的时候可以减少跟其他库冲突。

(function () { 
var hello = 'Hello World.'; 
})(); 
alert(hello); //error: hello no exist.

这里的语法很有点诡异,主要思想是定义一个匿名方法,并且马上执行。由于function开头这个litertal会被解释作为函数定义,这里加上了一对括号包住它,然后再用一对括号表示调用此函数。外部的alert访问不到在函数内部定义的hello。

陷阱一:var的陷阱

“减缓全局变量污染全局空间”的例子改成

(function () { 
hello = 'Hello World.'; //remove var 
})(); 
alert(hello); //alert ('Hello World.');

当变量hello没有用var显式声明时,hello成为了一个全局变量!!

虽然利用这个特性,咱们可以提供一个对外接口,但不建议这样做。

(function () { 
var hello = 'Hello World.'; 
sayHello = function () { //不建议采用这种方式来提供接口,看起来很不明显。 
alert(hello); 
} 
})(); 
sayHello();

可以改进为
(function (window) { 
var hello = 'Hello World.'; 
window.$ = { 
sayHello: function () { 
alert(hello); 
} 
}; 
})(window); 
$.sayHello(); //看起来像jQuery那么酷

var obj = (function () { 
var hello = 'Hello World.'; 
return { 
sayHello: function () { 
alert(hello); 
} 
}; 
})(); 
obj.sayHello();

陷阱二: 闭包的陷阱

(function () { //函数a 
var arr = []; 
  var i = 0; 
var j; 
for ( ; i < 3; i++) { 
arr.push(function () { //函数b 
alert(i * 10); 
}); 
} 
for (j in arr) { 
arr[j](); 
} 
})();

原以为函数数组arr里各个函数执行后,会弹出0,10,20,但是结果不是如此。结果是弹出30,30,30。
函数b访问的不是当时的 i的值, 而是直接访问变量i(用于都是取i最新的值)。
原因是函数b是函数a的内部函数,变量i对函数b是可见的,函数b每次都从i处获取最新的值。

这次改成:

(function () { //函数a 
var arr = []; 
var i = 0; 
  var j; 
for ( ; i < 3; i++) { 
arr.push((function (anotherI) { //函数m 
return function () { //函数b 
alert(anotherI * 10); 
} 
})(i)); // 此处为(function b(anotherI) {})(i) 
} 
for (j in arr) { 
arr[j](); 
} 
})();

这次执行后,终于弹出0,10,20。这是为什么呢。

函数b访问的是anotherI(当时的i的值),而不是直接访问变量i。
每次在arr.push前,都会定义一个新匿名的函数m。本例中定义了3个匿名函数m0,m1,m2,每当被调用后,他们的anotherI都得到当前i的值。每个m函数执行后都返回一个b函数。b0在m0里,b1在m1里,b2在m2里。b0只能访问m0的anotherI(为0),而b0访问不了m1的anotherI,因为m0和m1为不同的函数。

Javascript 相关文章推荐
js资料prototype 属性
Mar 13 Javascript
关于javascript document.createDocumentFragment()
Apr 04 Javascript
ExtJS下grid的一些属性说明
Dec 13 Javascript
jQuery div层的放大与缩小简单实现代码
Mar 28 Javascript
js和jQuery设置Opacity半透明 兼容IE6
May 24 Javascript
深入理解Angular2 模板语法
Aug 07 Javascript
老生常谈js数据类型
Aug 03 Javascript
JavaScript html5 canvas实现图片上画超链接
Oct 20 Javascript
基于js中this和event 的区别(详解)
Oct 24 Javascript
对vue中的事件穿透与禁止穿透实例详解
Oct 28 Javascript
js 数组当前行添加数据方法详解
Jul 28 Javascript
jQuery实现动态加载瀑布流
Sep 01 jQuery
JavaScript.The.Good.Parts阅读笔记(一)假值与===运算符
Nov 16 #Javascript
javascript Array对象基础知识小结
Nov 16 #Javascript
纯js实现背景图片切换效果代码
Nov 14 #Javascript
基于jquery的自定义鼠标提示效果 jquery.toolTip
Nov 14 #Javascript
cnblogs中在闪存中屏蔽某人的实现代码
Nov 14 #Javascript
基于MooTools的很有创意的滚动条时钟动画
Nov 14 #Javascript
javascript 学习笔记(onchange等)
Nov 14 #Javascript
You might like
牡丹941资料
2021/03/01 无线电
PHP UTF8中文字符截断函数代码
2012/09/11 PHP
使用ob系列函数实现PHP网站页面静态化
2014/08/13 PHP
smarty半小时快速上手入门教程
2014/10/27 PHP
ThinkPHP水印功能实现修复PNG透明水印并增加JPEG图片质量可调整
2014/11/05 PHP
PHP爬虫之百万级别知乎用户数据爬取与分析
2016/01/22 PHP
thinkPHP简单实现多个子查询语句的方法
2016/12/05 PHP
PHP中仿制 ecshop验证码实例
2017/01/06 PHP
HR vs CL BO3 第二场 2.13
2021/03/10 DOTA
FF IE浏览器修改标签透明度的方法
2014/01/27 Javascript
微信内置浏览器私有接口WeixinJSBridge介绍
2015/05/25 Javascript
js倒计时简单实现代码
2016/08/11 Javascript
SpringMVC简单整合Angular2的示例
2017/07/31 Javascript
react路由配置方式详解
2017/08/07 Javascript
Javascript防止图片拉伸的自适应处理方法
2017/12/26 Javascript
[05:43]VG.R战队教练Mikasa专访:为目标从未停止战斗
2016/08/02 DOTA
Python实现全角半角转换的方法
2014/08/18 Python
Python命令行参数解析模块optparse使用实例
2015/04/13 Python
python读取TXT到数组及列表去重后按原来顺序排序的方法
2015/06/26 Python
Python编程之微信推送模板消息功能示例
2017/08/21 Python
python opencv之SIFT算法示例
2018/02/24 Python
python基础教程项目二之画幅好画
2018/04/02 Python
Python爬虫实现全国失信被执行人名单查询功能示例
2018/05/03 Python
解决phantomjs截图失败,phantom.exit位置的问题
2018/05/17 Python
Python饼状图的绘制实例
2019/01/15 Python
在python中将list分段并保存为array类型的方法
2019/07/15 Python
django foreignkey(外键)的实现
2019/07/29 Python
python数据类型强制转换实例详解
2020/06/22 Python
解决Ubuntu18中的pycharm不能调用tensorflow-gpu的问题
2020/09/17 Python
C++如何引用一个已经定义过的全局变量
2014/08/25 面试题
实习生求职自荐信
2014/02/07 职场文书
民生工作实施方案
2014/05/31 职场文书
运动会口号8字
2014/06/07 职场文书
学校组织向国旗敬礼活动方案(中小学适用)
2014/09/27 职场文书
python中os.path.join()函数实例用法
2021/05/26 Python
Nginx 502 bad gateway错误解决的九种方案及原因
2022/08/14 Servers