zoukankan      html  css  js  c++  java
  • 模仿$.Callbacks实现

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            1.add的参数兼容,比如cb.add(fn1).add(fn2)等同于add(fn1,fn2)等同于add([fn1,fn2])。
            2.$.Callbacks("memory"),第一次fire,执行之前的函数队列。fire之后add的时候,就执行加入的函数。
            3.$.Callbacks("unique"),add的时候判断当前函数,是否已存于执行队列中。
            4.$.Callbacks("once"),第一次fire的时候,打个标记表明once了。第二次fire的时候,有once,就不执行队列。
            5.$.Callbacks("stopOnFalse"),判断执行队列中函数的执行结果,为false,则中断函数队列的遍历执行。
            6.$.Callbacks("memory once"),字符串对象化,使得字符串顺序变换也没关系。之后各回各家,该干嘛干嘛去。
            7.$.Callbacks是一个对象工厂。
            8.$.Callbacks的lock和disable的区别。lock只是不再add,但还能fire。disable不仅不能add,连fire也不行。
            9.$.Callbacks的remove方法,就是从队列去除指定函数。
            10.fire的时候可以指定上下文
        </body>
        <script type="text/javascript">
            function showType(type, obj) {
                var clas = Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
                return obj !== undefined && obj !== null && clas === type;
            }
            
            var $={};
            
            // 依赖  类型判断showType,遍历处理
            $.Callbacks = function(strArg){
                
                var list = [];
                var fired_flag=false;
                var lock_flag=false ,disable_flag = false;
                var str_list = strArg.split(" ");
                var fire_args = [];
                
                var cbArg_obj = {
                    "once":false,
                    "unique":false,
                    "memory":false,
                    "stopOnFalse":false
                };
                
                for(var i=0,l=str_list.length; i<l; i++){
                    cbArg_obj[str_list[i]] = true;
                }
                
                var once_flag = cbArg_obj["once"],
                unique_flag= cbArg_obj["unique"], 
                memory_flag= cbArg_obj["memory"], 
                stopOnFalse_flag= cbArg_obj["stopOnFalse"];
                
                
                var self = {
                    "add":function(){
                        if(lock_flag || disable_flag){
                            return;
                        }
                        // 参数兼容
                        var arg = arguments;
                        (function add(arg){
                            for(var i=0,l = arg.length; i< l; i++){
                                var argItem = arg[i];
                                if(list.indexOf(argItem)>-1 && unique_flag){
                                    return;
                                }
                                if(showType("function",argItem) ){
                                    list.push(argItem);
                                    if(memory_flag && fired_flag){
                                        argItem.apply(null,fire_args);
                                    }
                                }
                                else if(showType("array",argItem)){
                                    add(argItem);
                                }
                            }
                        })(arg);
                                    
                        
                        // 为了链性调用
                        return this;
                    },
                    "fire":function(){
                        if( (once_flag && fired_flag) || disable_flag){
                            return;
                        }
                        if(arguments.length){
                            fire_args = arguments || [];
                        }
                        for(var i =0,l= list.length; i< l; i++){
                            if( (list[i].apply(this,fire_args) == false) && stopOnFalse_flag){
                                break;
                            }
                        }
                        fired_flag = true;
                    },
                    "remove":function(fn){
                        for(var i=0,l= list.length; i<l; i++){
                            if(list[i] == fn){
                                list.splice(i,1);
                            }
                        }
                    },
                    "lock":function(){
                        lock_flag = true;
                    },
                    "disable":function(){
                        disable_flag = true;
                    }
                };
                return self;
            };
            
            function fn1(){
                alert(1);
            }
            
            function fn2(){
                alert(2);
            }
            function fn3(){
                alert(3);
            }
            function fn4(){
                alert(4);
            }
            function fnThis(arg){
                alert(arg);
            }
            function fnFalse(){
                return false;
            }
            var cb = $.Callbacks("once memory");
            cb.add(fn1).add(fn2).add(fn4);
            cb.fire("hi");
            cb.add(fnThis);
            cb.fire("aaa");
        </script>
    </html>

    源代码阅读这件事:

    第一步,查看API。先明白这些API怎么用,因为API就是这些代码的需求。

    第二步,思考为什么这么写。一个需求实现,可以有多种实现方式。但是作者偏偏用这种,是为了代码性能优化、解耦,抑或偷懒?

    第三步,自己重新实现。有时候,第二步你怎么想,也想不出作者这样写的原因。自己动手重新实现,实现过程中,才更能理解作者的用心。

  • 相关阅读:
    vue-element-admin中table分页改为前台处理
    vue项目如何部署到Tomcat中
    vuex之modules 热加载(hot update)
    持续学习
    css比较特殊选择器汇总(持续更新)
    关于伪元素before after总结
    ajax入门-实现省份下拉框
    super和this关键字的详解
    监听器
    当浏览器被关闭时,session是否被关闭?
  • 原文地址:https://www.cnblogs.com/samwu/p/4287105.html
Copyright © 2011-2022 走看看