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 相关文章推荐
javascript 日历提醒系统( 兼容所有浏览器 )
Apr 07 Javascript
Javascript insertAfter() 实现函数代码
Oct 12 Javascript
sencha touch 模仿tabpanel导航栏TabBar的实例代码
Oct 24 Javascript
JavaScript汉诺塔问题解决方法
Apr 21 Javascript
jQuery基于toggle实现click触发DIV的显示与隐藏问题分析
Jun 12 Javascript
JS封装的自动创建表格的实现代码
Jun 15 Javascript
Web前端框架Angular4.0.0 正式版发布
Mar 28 Javascript
详解如何使用webpack打包Vue工程
May 27 Javascript
基于vue中css预加载使用sass的配置方式详解
Mar 13 Javascript
浅析js中mvvm模式实现的原理
Oct 06 Javascript
RxJS在TypeScript中的简单使用详解
Apr 13 Javascript
Vue仿Bibibili首页的问题
Jan 21 Vue.js
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
DIY一个适配电脑声卡的动圈话筒放大器
2021/03/02 无线电
php 删除cookie和浏览器重定向
2009/03/16 PHP
php 空格,换行,跳格使用说明
2009/12/18 PHP
PHP JSON格式数据交互实例代码详解
2011/01/13 PHP
ThinkPHP中的系统常量和预定义常量集合
2014/07/01 PHP
yii实现级联下拉菜单的方法
2014/07/31 PHP
PHP模板解析类实例
2015/07/09 PHP
php验证码生成代码
2015/11/11 PHP
高质量PHP代码的50个实用技巧必备(上)
2016/01/22 PHP
YII2框架中excel表格导出的方法详解
2017/07/21 PHP
php通过header发送自定义数据方法
2018/01/18 PHP
PHP实现微信红包金额拆分试玩的算法示例
2018/04/07 PHP
通过PHP实现获取访问用户IP
2020/05/09 PHP
新闻内页-JS分页
2006/06/07 Javascript
3Z版基于jquery的图片复选框(asp.net+jquery)
2010/04/12 Javascript
js固定DIV高度,超出部分自动添加滚动条的简单方法
2013/07/10 Javascript
form.submit()不能提交表单的原因分析
2014/10/23 Javascript
javascript使用正则表达式检测IP地址
2014/12/03 Javascript
解析javascript中鼠标滚轮事件
2015/05/26 Javascript
JS自动倒计时30秒后按钮才可用(两种场景)
2015/08/31 Javascript
javascript html5移动端轻松实现文件上传
2020/03/27 Javascript
Angularjs中使用Filters详解
2016/03/11 Javascript
jQuery插件ajaxFileUpload使用详解
2017/01/10 Javascript
解决koa2 ctx.render is not a function报错问题
2018/08/07 Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
2018/08/20 Javascript
vue+axios 前端实现的常用拦截的代码示例
2018/08/23 Javascript
Vue页面跳转动画效果的实现方法
2018/09/23 Javascript
Python爬虫 urllib2的使用方法详解
2019/09/23 Python
python模拟实现斗地主发牌
2020/01/07 Python
tensorflow 固定部分参数训练,只训练部分参数的实例
2020/01/20 Python
Windows 平台做 Python 开发的最佳组合(推荐)
2020/07/27 Python
HTML5中新标签和常用标签详解
2014/03/07 HTML / CSS
使用javascript和HTML5 Canvas画的四渐变色播放按钮效果
2014/04/10 HTML / CSS
大专生找工作自荐书
2014/06/10 职场文书
Python实现8种常用抽样方法
2021/06/27 Python
分析JVM源码之Thread.interrupt系统级别线程打断
2021/06/29 Java/Android