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之卸载鼠标事件的代码
May 14 Javascript
使用jQuery模板来展现json数据的代码
Oct 22 Javascript
JS实现网页上随机产生超链接地址的方法
Nov 09 Javascript
详解Wondows下Node.js使用MongoDB的环境配置
Mar 01 Javascript
实例剖析AngularJS框架中数据的双向绑定运用
Mar 04 Javascript
BootStrap中
Dec 10 Javascript
js和jquery中获取非行间样式
May 05 jQuery
微信小程序自定义可滑动顶部TabBar选项卡实现页面切换功能示例
May 14 Javascript
bootstrap table插件动态加载表头
Jul 19 Javascript
JS实现星星海特效
Dec 24 Javascript
简单了解Vue + ElementUI后台管理模板
Apr 07 Javascript
JavaScript快速调试的两个技巧
Nov 04 Javascript
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
深入解析php之apc
2013/05/15 PHP
JavaScript Event学习第六章 事件的访问
2010/02/07 Javascript
自己做的模拟模态对话框实现代码
2012/05/23 Javascript
基于jQuery实现下拉框
2014/11/24 Javascript
原生js实现autocomplete插件
2016/04/14 Javascript
微信小程序中使用Promise进行异步流程处理的实例详解
2017/08/17 Javascript
js捆绑TypeScript声明文件的方法教程
2018/04/13 Javascript
BootStrap modal实现拖拽功能
2018/12/01 Javascript
jQuery提示框插件SweetAlert用法分析
2019/08/05 jQuery
JavaScript工具库MyTools详解
2020/01/01 Javascript
[05:56]第十六期——新进3大C之小兔基
2014/06/24 DOTA
[01:26]DOTA2荣耀之路2:iG,China
2018/05/24 DOTA
Python爬取网易云音乐热门评论
2017/03/31 Python
Python 用Redis简单实现分布式爬虫的方法
2017/11/23 Python
Python嵌套列表转一维的方法(压平嵌套列表)
2018/07/03 Python
Python发送邮件测试报告操作实例详解
2018/12/08 Python
详解如何用TensorFlow训练和识别/分类自定义图片
2019/08/05 Python
Python reshape的用法及多个二维数组合并为三维数组的实例
2020/02/07 Python
python GUI库图形界面开发之PyQt5下拉列表框控件QComboBox详细使用方法与实例
2020/02/27 Python
详解css3中dispaly的Grid布局与Flex布局
2020/09/11 HTML / CSS
Html5 audio标签样式的修改
2016/01/28 HTML / CSS
全球知名鞋履品牌授权零售商:Journeys
2016/09/17 全球购物
SISLEY希思黎官方旗舰店:享誉全球的奢华植物美容品牌
2018/04/25 全球购物
金士达面试非笔试
2012/03/14 面试题
电子商务应届生求职信
2013/11/16 职场文书
校园摄影活动策划方案
2014/02/05 职场文书
陈欧的广告词
2014/03/18 职场文书
志愿者活动总结
2014/04/28 职场文书
统计学教授推荐信
2014/09/18 职场文书
2014年电话销售工作总结
2014/12/01 职场文书
2014年煤矿安全工作总结
2014/12/04 职场文书
2015个人半年总结范文
2015/03/09 职场文书
圣诞晚会主持词开场白
2015/05/28 职场文书
学校体育节班级口号
2015/12/25 职场文书
SpringBoot2零基础到精通之数据库专项精讲
2022/03/22 Java/Android
海康机器人重磅发布全新算法开发平台VM4.2
2022/04/21 数码科技