面向对象的 Javascript(5)
作者:mozart0 来源:蓝色经典 发布时间:2013-07-21 11:57:22
闭包
闭包意味着内层的函数可以引用存在于包绕它的函数的变量,即使外层的函数的执行已经终止。这一特殊的论题可能是非常强大又非常复杂的。我强烈推荐你们参考本节后面将提及的站点,因为它有一些关于闭包这一话题的精彩的信息。
我们先来看程序2-13所示的闭包的两个简单例子。
程序2-13. 闭包改善的代码清晰性的两例
//得到id为"main"的元素
var obj = document.getElementById("main");
//改变它的边框样式
obj.style.border = "1px solid red";
//初始化一个1秒钟以后被调用的回调函数
setTimeout(function(){
//此函数将隐藏该元素
obj.style.display = 'none';
}, 1000);
//用来延迟显示消息的通用函数
function delayedAlert( msg, time ) {
//初始化一个被封套的函数
setTimeout(function(){
//此函数使用了来自封套它的函数的变量msg
alert( msg );
}, time );
}
//调用函数delayedAlert,带两个参数
delayedAlert( "Welcome!", 2000 );
第一个对setTimeout的函数调用,展示了一个的JavaScript新手遇到问题的通俗的例子。在JavaScript新手的程序里像这样的代码时常可以看到:
setTimeout("otherFunction()", 1000);
//或者甚至
setTimeout("otherFunction(" + num + "," + num2 + ")", 1000);
使用闭包的概念,完全可能的把这种混乱的代码清理掉。第一个例子很简单;有一个回调函数在调用setTimeout函数以后1000微秒以后被调用,而它仍引用了变量obj(定义在全局范围,指向id为"main"的元素)。定义的第二个函数,delayedAlert,展示了一种解决出现的setTimeout混乱的方案,以及函数作用域内可以有闭包的能力。
你们应该可以发现,当在代码中使用这种简单的闭包时,你所写的东西的清晰性将会提高,免于陷入语法的迷雾之中。
我们来看一个闭包可能带来的有有趣的副作用。在某些函数化的编程语言里,有一个叫做currying的概念。本质上讲,currying是就是为函数的一些参数预填入值,创建一个更简单的新函数的方法。代码2-14里有一个简单的currying的例子,创建了向另一个函数预填一个参数而得的新函数。
代码2-14. 使用闭包的函数currying
//生成做加法的新函数的函数
function addGenerator( num ) {
//返回一个简单函数用来计算两个数的加法,
//其中第一个数字从生成器中借用
return function( toAdd ) {
return num + toAdd
};
}
//addFive现在是接受一个参数的函数,
//此函数将给参数加5,返回结果数字
var addFive = addGenerator( 5 );
//这里我们可以看到,当传给它参数4的时候
//函数addFive的结果为9
alert( addFive( 4 ) == 9 );
闭包还能解决另一个常见的JavaScript编码方面的问题。JavaScript新手趋向于在全局作用域里放置许多变量。这一般被认为是不好的习惯,因为那些变量可能悄悄地影响其它的库,导致令人迷惑的问题的产生。使用一个自执行的、匿名的函数,你可以从根本上隐藏所有的通常的全局变量,使它们对其它代码不可见,如程序2-15所示。
代码2-15. 使用匿名函数从全局作用域隐藏变量的例子
//创建一个用作包装的匿名函数
(function(){
//这个变量通常情况下应该是全局的
var msg = "Thanks for visiting!";
//为全局对象绑定新的函数
window.onunload = function(){
//使用了“隐藏”的变量
alert( msg );
};
//关闭匿名函数并执行之
})();
最后,让我们来看使用闭包时出现的一个问题。闭包允许你引用存在于父级函数中的变量。然而,它并不是提供该变量创建时的值;它提供的是父级函数中该变量最后的值。你会看到这个问题最通常是在一个for循环中。有一个变量被用作迭代器(比如i),在for内部新的函数被创建,并使用了闭包来引用该迭代器。问题是,当新的闭包函数被调用时,它们将会引用该iterator最后的值(比如,一个数组的最后位置),而不是你所期望的那个。程序2-16的例子说明,使用匿名函数激发作用域,在其中创建一个合乎期望的闭包是可能的。
程序2-16. 使用匿名函数激发一个创建多个闭包函数所需的作用域的例子
//id为"main"的一个元素
var obj = document.getElementById("main");
//用来绑定的items数组
var items = [ "click", "keypress" ];
//遍历items中的每一项
for ( var i = 0; i < items.length; i++ ) {
//用自执行的匿名函数来激发作用域
(function(){
//在些作用域内存储值
var item = items[i];
//为obj元素绑定函数
obj[ "on" + item ] = function() {
//item引用一个父级的变量,
//该变量在此for循环的上文中已被成功地scoped(?)
alert( "Thanks for your " + item );
};
})();
}
闭包的概念并非轻易可以掌握的;我着实花了大量的时间和精力才彻底弄清闭包有多么强大。幸运的是,有一个精彩的资源解释了JavaScript中的闭包是怎么工作的:Jim Jey的"JavaScript闭包",网址是http://jibbering.com/faq/faq_notes/closures.html。
最后,我们将研究上下文的概念,这是许多JavaScript的面向对象特性赖以建立的基石。


猜你喜欢
- 在使用Jupyter notebook时有这么一句代码start_frame = imread(“OwnCollection\vehicle
- 下面的代码中python2与python3的print使用区别,大家注意一下。python3需要加()才行。语法:for循环的语法格式如下:
- 前言看到这篇文章我就默认你已经在你的电脑上使用 pipenv搭建好了虚拟环境并且设置好了开发环境(pycharm)。如果没有,请参照这篇文章
- 先看一下效果图: index.wxml <view class='{{tabIsTop ? "fixedT
- 这篇文章主要介绍了基于Python执行dos命令并获取输出的结果,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值
- 1:获取对象的三种方法1)document.getElementById(id);通过对象的属性id来获取;2)element.getEle
- 一、前言昨夜刷b站的时候,看到了一条评论,形式如下图,于是心血来潮写了个python脚本,可以根据文字来生成这种由emoji拼接成的“文字”
- 装饰器(Decorators)装饰器是这样一种设计模式:如果一个类希望添加其他类的一些功能,而不希望通过继承或是直接修改源代码实现,那么可以
- 说起来惭愧,总是犯一些小错误,纠结半天,这不应为一个分号的玩意折腾了好半天! 错误时在执行SQL语句的时候发出的,信息如下: Java代码
- 本文介绍使用aspjpeg组件实现图片的半透明描边的效果,描边效果演示:参数说明'big 原图路径(相对)'small 生成
- 一直不用这个phpmyadmin,在本机也是用navicat,总感觉phpmyadmin速度较慢。这回不行了,没有独立主机,只好用人家给的p
- 大家都知道对于一个页面来说,最基本的结构呢就是<html> <head> <!-- 头部信息内容区域
- 一、什么是线程?线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程。车间负责把资源整合到一起,
- 本文实例讲述了Python文本统计功能之西游记用字统计操作。分享给大家供大家参考,具体如下:一、数据xyj.txt,《西游记》的文本,2.2
- python语言中的列表排序方法有三个:reverse反转/倒序排序、sort正序排序、sorted可以获取排序后的列表。在更高级列表排序中
- 本文来源于Element官方文档:http://element-cn.eleme.io/#/zh-CN/component/carousel
- 因为权限不够,导致Pycharm在运行脚本时报错:socket.error: [Errno 1] Operation not permitt
- pygame绘制机制简介 屏幕控制 pygame.display• 用来控制Pygame游戏的屏幕• Pygame有且只有一个屏幕
- 本文实例为大家分享了python实现桌面托盘气泡提示的具体代码,供大家参考,具体内容如下# -*- encoding:utf-8 -*- #
- 栈溢出const data = { foo: 1 }const obj = new Proxy(data, {/*...*/})effect