zoukankan      html  css  js  c++  java
  • 透过Extjs学习JavaScript---闭包篇

    目录

    一、前言
    四、总结

    一、前言

    JavaScript设计得最出色的就是它的函数的实现,它几乎接近于完美。我们现在现就来介绍它其中一个功能“闭包”。我们可以利用闭包“保存变量生命周期”和“屏蔽变量”的特性优雅地完成一些强大的功能。后面我还会介绍在ExtJS中是如何使用这种特性的。

    二、基础讲解

    我们可以利用“闭包”功能来实现隐藏或公开对象的变量和方法。

    测试代码如下

     1 var bufferObj = (function createFun(fn, interval, scope) {
     2     var isExec = 1;//被闭包的变量,外界不能直接访问
     3     return {//公开set,和exec方法
     4         set : function(data) {
     5             isExec = data;
     6         },
     7         exec : function(fn) {
     8             if (isExec) {//读取闭包的变量
     9                 console.log("函数可以执行");
    10                 fn();
    11             } else {
    12                 console.log("函数不能执行");
    13             }
    14         }
    15     };
    16 })();

    注意我们把整个函数用括号包住,并在最后一行加了"()",这样写法的意思是马上执行函数,并返回了结果值。这样我们的变量“bufferObj”对象就是带有公开的set和exec方法和私有变量“isExec”。我不能直接访问到“isExec”这个变量,这就是我们使用闭包的结果,将一些变量或方法优雅的变成私有,很好的控制了变量的作用域。

    三、知识应用

    上节初步的说明了闭包的写法和功能,看似功能不过如此,其实不然。下面我们来看看ExtJs是如何使用闭包功能的,希望可以给大家在使用闭包有更多的启发。这也是学习JS这门语言有兴趣的地方,是把一个简简单单的知识点写出多种花样。

    下面的代码是extjs中“Ext.Function”类中的“createBuffered”方法,主要功能就是生成“带有延迟功能的函数”。我为了简化“Ext.Function”类的上下文,并把代码标上的汉语解释方便讲解。

    Ext.Function 代码如下:

     1 var Ext = {};
     2 Ext.Function = {
     3     /**
     4      * 返回带有延迟功能的函数,如果在延迟的时间内再次调用该函数,重置缓冲时间
     5      * @param {Function} fn 需要被延迟的方法
     6      * @param {Number} buffer 延迟时间(毫秒)
     7      * @param {Object} [scope=this] 传入方法的作用域
     8      * @param {Array} [args] 方法参数
     9      * @return {Function} 返回带有缓冲功能的函数
    10      */
    11     createBuffered: function(fn, buffer, scope, args) {
    12         var timerId;//计时器ID
    13 
    14         return function() {
    15             var callArgs = args || Array.prototype.slice.call(arguments, 0),//将“arguments”类型转成数组类型
    16                 me = scope || this;//如果没有传入“scope”参数就全用当前上下文的"this"为作用域
    17 
    18             if (timerId) {//如果有计时器,就取消之前的计时器
    19                 clearTimeout(timerId);
    20             }
    21 
    22             timerId = setTimeout(function(){//重置缓冲时间
    23                 fn.apply(me, callArgs);//在相应的作用域上执行方法
    24             }, buffer);
    25         };
    26     }
    27 };

    在上述代码中把变量“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”值。

    使用代码如下:

     1 var run = function(data) {
     2     alert("函数运行成功");
     3     alert("入参为:" + data);
     4 };
     5 var bufferFn = Ext.Function.createBuffered(run, 3000);
     6 bufferFn("JavaScript1");//不会被执行,因为后一个函数在缓冲期3秒内调用,把这当前的函数取消了
     7 bufferFn("JavaScript2");//不会被执行,因为后一个函数在缓冲期3秒内调用,把这当前的函数取消了
     8 bufferFn("JavaScript3");//会被执行,因为后一个函数没有在缓冲期3秒内调用,所以该函数会执行
     9 
    10 setTimeout(function() {//间隔4秒
    11     bufferFn("JavaScript4");//会被执行,因为后面没有重复调用了
    12 }, 4000);

     在上述代码第5行,就是通过“Ext.Function.createBuffered”生成了一个带有缓冲功能的函数“bufferFn”,如果我们在3秒的缓冲期内重复调用就不会重复执行函数。

    四、总结

    1. 笔者的案例代码是取自于ExtJs,可能有些不好理解,但是当你看懂了,就能感觉到JS这门语言的巧妙。
    2. 文本只是通过介绍闭包的方法,进而介绍下ExtJs的源码,使我们撸代码的水平有所提升。

    五、常见问题

    • 问:有的人会问这创建延迟函数有什么用?感觉在实际情况下用不到? 
      答:笔者可不这么认为,我在做项目中就常常用到这种方法。当我们要对一个输入框发生内容改变时,进行AJAX查询。但又不想每输入一个字就进行一次查询,因为这样非常的消耗服务器资源。较好的解决方案是设置一个输入缓冲期,在这个输入缓冲期内输入字母不进行查询,等过了缓冲期在对之前输入过的所有字母进行查询,所以我们需要一个“带有延迟缓冲功能”的函数。
    • 问:arguments这到底是什么? 
      答:好吧,详细请访问http://www.w3school.com.cn/js/pro_js_functions_arguments_object.asp,arguments是一个特殊的对象,类似于数组,但不完全是数组,所以要用“Array.prototype.slice.call(arguments, 0)”方法转成常规的数组。
  • 相关阅读:
    Hibernate save, saveOrUpdate, persist, merge, update 区别
    Eclipse下maven使用嵌入式(Embedded)Neo4j创建Hello World项目
    Neo4j批量插入(Batch Insertion)
    嵌入式(Embedded)Neo4j数据库访问方法
    Neo4j 查询已经创建的索引与约束
    Neo4j 两种索引Legacy Index与Schema Index区别
    spring data jpa hibernate jpa 三者之间的关系
    maven web project打包为war包,目录结构的变化
    创建一个maven web project
    Linux下部署solrCloud
  • 原文地址:https://www.cnblogs.com/lmm0591/p/3552904.html
Copyright © 2011-2022 走看看