• 利用递归统一化函数参数的不固定数据类型


    为了用户调用函数时更方便和灵活,所以我们定义的参数需要不固定数据类型,比如像这样:

    mylibs.on('event',fn);

    mylibs.on({
        'event1':fn1,
        'event2':fn2,
        'event3':fn3
    });

    mylibs.on('event1 event2 event3',fn);

    这是一个自定义事件的例子,有三种传参的方式:1、事件名+回调   2、传递一个对象包含事件名和回调    3、多个事件名+一个回调

    你觉得这个函数怎么写才好呢,也许大多数人首先想到的是统一数据类型再处理具体的逻辑,就像下面这样:

    //匹配任何空白符,包括
    ,
    ,f,	,v等(换行、回车、空格、tab等)
    var eventSplitter = /s+/;
    
    var mylibs = {
        on:function(name, callback, context){
    
            if(typeof name === 'string'){
                name = {name:callback};
            }
                
            if (eventSplitter.test(name)) {
                var names = name.split(eventSplitter),
                    name = {};
                for (var i = 0, length = names.length; i < length; i++) {
                    name[names[i]] = callback;
                }
            }
                
            //统一好了数据类型则执行循环(默认数据类型是对象,所以在上面不做判断)
            for(var key in name){
                //具体逻辑......
            }
            return this;
        }
    };

    这种写法看似不错,先统一处理数据类型,解决了参数不同的问题。不过函数看上去稍显臃肿,如果参数再增加几种类型,那么相应的也会在函数体内增加判断语句,并且把具体的逻辑代码放在for循环内也不是一种优雅的做法。

    我们可以尝试一下把判断语句提炼出来,写在一个单独的函数里。

    var mylibs = {
        on:function(name, callback, context){
    
            name = this.eventsApi(name,callback);
    
            for(var key in name){
                //具体逻辑......
            }
            return this;
        },
        eventsApi:function(name,callback){
            if(typeof name === 'string'){
                return {name:callback};
            }    
            if (eventSplitter.test(name)) {
                var names = name.split(eventSplitter),
                    name = {};
                for (var i = 0, length = names.length; i < length; i++) {
                    name[names[i]] = callback;
                }
                return name;
            }
            return name;
        }
    };

    创建了eventsApi函数来对数据类型做统一处理,很明显on函数已经不臃肿了,2个函数各司其职。但是on函数的具体逻辑代码仍然在for循环内,我们得想办法把它抽离出来。

    解决的办法可以利用递归,我们先处理一下eventsApi函数。

    eventsApi:function(obj,action,name,rest){
        if (!name) return true;
    
        if(typeof name === 'object'){
            for(var key in name){
                obj[action].apply(obj,[key,name[key]].concat(rest));
            }
            return false;
        }
        if (eventSplitter.test(name)) {
            var names = name.split(eventSplitter);
            for (var i = 0, length = names.length; i < length; i++) {
                obj[action].apply(obj, [names[i]].concat(rest));
            }
            return false;
        }
        return true;
    }

    是不是眼前一亮,eventsApi函数并没有统一处理数据类型,而是直接调用on函数,此时on函数变成了一个固定数据类型的函数了,其实就是上面第一种传参的形式:一个事件名+回调。

    我们看一下完整的代码加深理解吧。

    //匹配任何空白符,包括
    ,
    ,f,	,v等(换行、回车、空格、tab等)
    var eventSplitter = /s+/;
    
    var mylibs = {
        on:function(name, callback, context){
            if (!this.eventsApi(this, 'on', name, [callback, context]) || !callback) return this;
            //具体逻辑......
            return this;
        },
        eventsApi:function(obj,action,name,rest){
            if (!name) return true;
    
            if(typeof name === 'object'){
                for(var key in name){
                    obj[action].apply(obj,[key,name[key]].concat(rest));
                }
                return false;
            }
            if (eventSplitter.test(name)) {
                var names = name.split(eventSplitter);
                for (var i = 0, length = names.length; i < length; i++) {
                    obj[action].apply(obj, [names[i]].concat(rest));
                }
                return false;
            }
            return true;
        }
    };
    
    //调用:
    mylibs.on('event',fn);
    mylibs.on({
        'event1':fn1,
        'event2':fn2,
        'event3':fn3
    });
    mylibs.on('event1 event2 event3',fn);
  • 相关阅读:
    从代码书写理解指针,很重要
    指针参数 引用参数
    [转载]c/c++ 操作sqlite
    [转载]C#.NET DataTable扩展 ToList/Get/OrderBy/Where/ToPage
    [转载]宏定义
    【转载】scanf,sscanf高级用法
    C开发机顶盒实战应用代码片段
    指针精华口诀,短小精悍
    C# linq泛型 字典集合 排序
    c开发机顶盒实战应用代码片段2
  • 原文地址:https://www.cnblogs.com/gongshunkai/p/5876700.html
Copyright © 2020-2023  润新知