透过Extjs学习JavaScript---闭包篇
目录
一、前言
JavaScript设计得最出色的就是它的函数的实现,它几乎接近于完美。我们现在现就来介绍它其中一个功能“闭包”。我们可以利用闭包“保存变量生命周期”和“屏蔽变量”的特性优雅地完成一些强大的功能。后面我还会介绍在ExtJS中是如何使用这种特性的。
二、基础讲解
我们可以利用“闭包”功能来实现隐藏或公开对象的变量和方法。
测试代码如下
var bufferObj = (function createFun(fn, interval, scope) {
var isExec = 1;//被闭包的变量,外界不能直接访问
return {//公开set,和exec方法
set : function(data) {
isExec = data;
},
exec : function(fn) {
if (isExec) {//读取闭包的变量
console.log("函数可以执行");
fn();
} else {
console.log("函数不能执行");
}
}
};
})();
注意我们把整个函数用括号包住,并在最后一行加了"()",这样写法的意思是马上执行函数,并返回了结果值。这样我们的变量“bufferObj”对象就是带有公开的set和exec方法和私有变量“isExec”。我不能直接访问到“isExec”这个变量,这就是我们使用闭包的结果,将一些变量或方法优雅的变成私有,很好的控制了变量的作用域。
三、知识应用
上节初步的说明了闭包的写法和功能,看似功能不过如此,其实不然。下面我们来看看ExtJs是如何使用闭包功能的,希望可以给大家在使用闭包有更多的启发。这也是学习JS这门语言有兴趣的地方,是把一个简简单单的知识点写出多种花样。
下面的代码是extjs中“Ext.Function”类中的“createBuffered”方法,主要功能就是生成“带有延迟功能的函数”。我为了简化“Ext.Function”类的上下文,并把代码标上的汉语解释方便讲解。
Ext.Function 代码如下:
var Ext = {};
Ext.Function = {
/**
* 返回带有延迟功能的函数,如果在延迟的时间内再次调用该函数,重置缓冲时间
* @param {Function} fn 需要被延迟的方法
* @param {Number} buffer 延迟时间(毫秒)
* @param {Object} [scope=this] 传入方法的作用域
* @param {Array} [args] 方法参数
* @return {Function} 返回带有缓冲功能的函数
*/
createBuffered: function(fn, buffer, scope, args) {
var timerId;//计时器ID
return function() {
var callArgs = args || Array.prototype.slice.call(arguments, 0),//将“arguments”类型转成数组类型
me = scope || this;//如果没有传入“scope”参数就全用当前上下文的"this"为作用域
if (timerId) {//如果有计时器,就取消之前的计时器
clearTimeout(timerId);
}
timerId = setTimeout(function(){//重置缓冲时间
fn.apply(me, callArgs);//在相应的作用域上执行方法
}, buffer);
};
}
};
在上述代码中把变量“timerId”闭包在对象内,只返回了一个带有缓冲功能的方法,该返回方法主要是判断函数在缓冲期内是否被重复调用,如果在缓冲期内被调用就重置计时器。
在代码中有三个知识点:
1. 15行中“Array.prototype.slice.call(arguments, 0)”这句意思是把arguments参数类型转成数组类型,方便第23行的“apply”调用。(如果不知道arguments是什么意思的同学就自行面壁思过吧,哈哈哈。)
2. 16行中"me = scope || this" ,是一个if判断取巧的写法。整句的意思是,当“scope”为“空”或“假”时就把“this”返回给“me”变量。
3. 18行中的“timerId”变量由于是被闭包,他的“生命期”被延长了,不会随着返回函数的运行结束而结束,所以每次调用返回函数时,都可以保留之前的“timerId”值。
使用代码如下:
var run = function(data) {
alert("函数运行成功");
alert("入参为:" + data);
};
var bufferFn = Ext.Function.createBuffered(run, 3000);
bufferFn("JavaScript1");//不会被执行,因为后一个函数在缓冲期3秒内调用,把这当前的函数取消了
bufferFn("JavaScript2");//不会被执行,因为后一个函数在缓冲期3秒内调用,把这当前的函数取消了
bufferFn("JavaScript3");//会被执行,因为后一个函数没有在缓冲期3秒内调用,所以该函数会执行
setTimeout(function() {//间隔4秒
bufferFn("JavaScript4");//会被执行,因为后面没有重复调用了
}, 4000);
在上述代码第5行,就是通过“Ext.Function.createBuffered”生成了一个带有缓冲功能的函数“bufferFn”,如果我们在3秒的缓冲期内重复调用就不会重复执行函数。
四、总结
- 笔者的案例代码是取自于ExtJs,可能有些不好理解,但是当你看懂了,就能感觉到JS这门语言的巧妙。
- 文本只是通过介绍闭包的方法,进而介绍下ExtJs的源码,使我们撸代码的水平有所提升。
五、常见问题
- 问:有的人会问这创建延迟函数有什么用?感觉在实际情况下用不到?
答:笔者可不这么认为,我在做项目中就常常用到这种方法。当我们要对一个输入框发生内容改变时,进行AJAX查询。但又不想每输入一个字就进行一次查询,因为这样非常的消耗服务器资源。较好的解决方案是设置一个输入缓冲期,在这个输入缓冲期内输入字母不进行查询,等过了缓冲期在对之前输入过的所有字母进行查询,所以我们需要一个“带有延迟缓冲功能”的函数。 - 问:arguments这到底是什么?
答:好吧,详细请访问http://www.w3school.com.cn/js/pro_js_functions_arguments_object.asp,arguments是一个特殊的对象,类似于数组,但不完全是数组,所以要用“Array.prototype.slice.call(arguments, 0)”方法转成常规的数组。
透过Extjs学习JavaScript---闭包篇的更多相关文章
- 一步步学习javascript基础篇(0):开篇索引
索引: 一步步学习javascript基础篇(1):基本概念 一步步学习javascript基础篇(2):作用域和作用域链 一步步学习javascript基础篇(3):Object.Function等 ...
- 一步步学习javascript基础篇(3):Object、Function等引用类型
我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂 ...
- [转载]学习Javascript闭包(Closure)
学习Javascript闭包(Closure) 源地址: http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures ...
- 一步步学习javascript基础篇(6):函数表达式之【闭包】
回顾前面介绍过的三种定义函数方式 1. function sum (num1, num2) { return num1 + num2; } //函数声明语法定义 2. var sum = funct ...
- 通过示例学习JavaScript闭包
译者按: 在上一篇博客,我们通过实现一个计数器,了解了如何使用闭包(Closure),这篇博客将提供一些代码示例,帮助大家理解闭包. 原文: JavaScript Closures for Dummi ...
- 一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)
上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 ...
- 一步步学习javascript基础篇(4):面向对象设计之创建对象(工厂、原型和构造函数等模式)
前面我们介绍了可以通过Object构造函数或对象字面量都可以用来创建单个对象,但是如果需要创建多个对象的话,显然很多冗余代码. 接下来介绍几种模式来创建对象.不过在此之前,我们还是先来了解下 type ...
- 一步步学习javascript基础篇(1):基本概念
一.数据类型 数据类型 基本数据类型(五种) Undefined Null Boolean Number String 复杂数据类型(一种) Object Undefined:只有一个值undefin ...
- 一步步学习javascript基础篇(8):细说事件
终于学到事件了,不知道为何听到“事件”就有一种莫名的兴奋.可能是之前的那些知识点过于枯燥无味吧,说起事件感觉顿时高大上了.今天我们就来好好分析下这个高大上的东西. 可以说,如果没有事件我们的页面就只能 ...
随机推荐
- 定制属于自己的Chrome起始页
个人感觉没什么技术含量,可是很有用.我定制的起始页面例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ19saWNodW4=/font/5 ...
- Core Foundation框架介绍
Core Foundation框架介绍 **参考网址: ARC下OC对象和CF对象之间的桥接 Core Foundation框架介绍 Core Foundation框架 Core Foundation ...
- 如何写好一个UITableView
本文是直播分享的简单文字整理,直播共分为上.下两部分. 第一部分: 优酷 :http://v.youku.com/v_show/id_XMTUzNzQzMDU0NA%3Cmark%3E.html Or ...
- TwoSAT算法模板
该模板来自大白书 [解释] 给多个语句,每个语句为“ Xi为真(假) 或者 Xj为真(假)” 每个变量和拆成两个点 2*i为假, 2*i+1为真 “Xi为真 或 Xj为真” 等价于 “Xi为假 –& ...
- (转)一步一步学习PHP(3)——函数
相信每个人在学习PHP之前至少都有着一定的C语言,或者是C++/Java/C#等其他语言的基础,所以在这里也不从头开始说起,只是来谈谈PHP方法的独特之处. 1. 方法概述 首先,写一个最简单的函数, ...
- Linux sed命令在指定行前后添加内容
一.在匹配行前后加内容在包含www.baidu.com的行前面或后面添加多一行内容www.qq.com#匹配行前加sed -i '/www.baidu.com/i www.qq.com' domain ...
- 【转】 iOS 两种方法实现左右滑动出现侧边菜单栏 slide view
原文: http://blog.csdn.net/crayondeng/article/details/9057637 --- 关于评论中,很多网友都是需要这部分的相关源码,其实在我上传的新浪微博 ...
- iPhone真机测试Crash信息分析
一.获取Crash Log的方式 在iOS开发过程,当应用已经打包,iPhone设备通过ipa的包安装应用后,在使用过程发现crash,那么如何获取crash日志呢,现提供如下四种获取crash日志的 ...
- PHP MySQL 插入多条数据
PHP MySQL 插入多条数据 使用 MySQLi 和 PDO 向 MySQL 插入多条数据 mysqli_multi_query() 函数可用来执行多条SQL语句. 以下实例向 "MyG ...
- C++ 实现网络爬虫
吐槽 前天心血来潮, 把自己面试经历下了下来. 我觉得自己求职一路来比较心酸, 也付出了比一般人更多的汗水. 本以为写出来, 好歹可以作为一篇励志故事. 得到的评论却是, 语言只是一门工具. ||| ...