本文实例讲述了JavaScript使用闭包模仿块级作用域操作。分享给大家供大家参考,具体如下:
在阅读这篇文章之前,建议先阅读JavaScript的作用域链以及JavaScript闭包。
正如闭包的定义一样:“闭包指的是有权访问另一个函数作用域中的变量的函数”, 闭包最大的意义就在于闭包可以对另一个函数作用域的变量进行访问,由此,闭包可以延伸出一系列的用法。
模仿块级作用域
JavaScript没有块级作用域的概念。这意味着在块语句中定义的变量,实际上是包含在函数中而非语句中创建的。从作用域链的角度来理解是,所有在函数内定义的变量(所有,也就是说块语句中定义的变量也包含在内)都会在这个函数执行时所创建的函数的活动对象中,因此从函数内的所有变量定义开始,就可以在函数内部随处访问它,闭包也可以通过作用域链访问它。
例子:
function outputNumbers(count){ for(var i = 0; i < count; i++){ console.log(i); // 0, 1, ... count - 1 } console.log(i); // count }
C++, JAVA等语言中,变量i只会在for循环的语句块(block)中有定义,循环一旦结束,变量i就会被销毁。可是在JavaScript中,变量i是定义在outputNumbers()的活动对象中,因此从函数内的所有变量定义开始,就可以在函数内部随处访问它,闭包也可以通过作用域链访问它。即使像下面这样重新声明同一个变量,也不会改变它的值。
function outputNumbers(count){ for(var i = 0; i < count; i++){ console.log(i); // 0, 1, ... count - 1 } var i; // redeclare i console.log(i); // count }
JavaScript从来不管是否多次声明了同一个变量;遇到这种情况,JavaScript只会对后续的声明视而不见(不过会执行后续声明中的变量初始化),将其当成一个赋值语句。
函数包装器可以用来模仿块作用域并避免这个问题。
函数包装器就是创建并立即调用一个函数。
(function(){ console.log("Hello World!"); })();
这段代码直接输出”Hello World”, 这就是一个函数包装器。
函数包装器的作用:
1. 立即执行函数中的代码,又不会再内存中留下对该函数的引用;
2. 函数内部的所有变量都会被立即销毁(除非将这些变量赋值给了包含作用域中的变量)。
当在函数内部使用函数包装器的时候,此时函数包装器就是一个闭包,有权访问外部环境中的所有变量。
function outputNumbers(count){ (function(){ //块级作用域 for(var i = 0; i < count; i++){ console.log(i); // 0, 1, ... count - 1 } })(); console.log(i); // error }
在函数包装器中可以访问外部环境outputNumbers()
的变量count,打印0, 1, … count - 1,但是在函数包装器执行完毕之后,再访问变量i就会抛出错误,因为i是在函数包装器中定义的,outputNumbers()
函数无法访问。
无论在什么地方,如果只需要一些临时变量,就可以使用块级作用域!
使用函数包装器这种闭包可以减少闭包过多占用内存的问题。因为没有指向匿名函数的引用, 所以只要函数包装器执行完毕,就可以立即销毁其作用域链了。
函数包装器这种技术经常在全局作用域中被用在函数外部,从而限制想全局作用域中添加过多的变量和函数。一般来说,我们都应该尽量少向全局作用域中添加变量和函数。过多的全局变量和函数很容易导致命名冲突。通过创建块级作用域,每个开发人员既可以使用自己的变量,有不必担心搞乱全局作用域。例如:
(function(){ var now = new Date(); if (now.getMonth() == 0 && now.getDate() == 1) { console.log("Happy new year"); } })();
将这段代码放在全局作用域中,可以用来确定哪天是一月一日。其中变量now现在是匿名函数中的局部变量,避免了在全局变量中创建。
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。