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

mylibs.on('event',fn);

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

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

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

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

//匹配任何空白符,包括\n,\r,\f,\t,\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函数变成了一个固定数据类型的函数了,其实就是上面第一种传参的形式:一个事件名+回调。

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

//匹配任何空白符,包括\n,\r,\f,\t,\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);

转载于:https://www.cnblogs.com/gongshunkai/p/5876700.html

利用递归统一化函数参数的不固定数据类型相关推荐

  1. php 函数传值_传址_函数参数,php函数的传值与传址(引用)详解

    在php中我们函数传值就比较简单了,但可能有些朋友地天真无邪函数传址或引用搞不明白,下面小编来给各位介绍在php中函数传值与传址(引用)介绍,希望对各位有所帮助. php中引用的用法: 1. 变量的引 ...

  2. php 函数传值_传址_函数参数,php函数的传值与传址(引用)详解_PHP教程

    在php中我们函数传值就比较简单了,但可能有些朋友地天真无邪函数传址或引用搞不明白,下面小编来给各位介绍在php中函数传值与传址(引用)介绍,希望对各位有所帮助. php中引用的用法: 1. 变量的引 ...

  3. 指针用作函数参数、指针型函数和函数指针

    指针用作函数参数 以前我们学过的函数参数要么是基本数据类型的变量,要么是类的对象,又或者是数组名,前几讲学到的指针同样可以用作函数参数. 指针作函数形参时,我们调用此函数将实参值传递给形参后,实参和形 ...

  4. 【C语言函数】 - 库函数、自定义函数、函数参数、函数调用、嵌套调用链式访问、递归与迭代、缓冲区

    目录 一.函数是什么 二.C语言中函数的分类 1.如何学会使用库函数 1.1.strcpy 1.2.memset 2.自定义函数 2.1.与库函数的区别 2.2.写一个函数可以找出两个整数的最大值 2 ...

  5. JavaScript学习笔记(四)---闭包、递归、柯里化函数、继承、深浅拷贝、设计模式

    JavaScript学习笔记(四)---闭包.递归.柯里化函数.继承.深浅拷贝.设计模式 1. 匿名函数的使用场景 2.自运行 3.闭包 3.1前提: 3.2闭包 4.函数对象的三种定义方式 5.th ...

  6. Learn day4 函数参数\变量\闭包\递归

    1.函数描述 # ### 函数 """ (1)函数的定义:功能 (包裹一部分代码 实现某一个功能 达成某一个目的) (2)函数特点:可以反复调用,提高代码的复用性,提高开 ...

  7. 利用递归实现JSON扁平化

    1.引入JSON依赖包 把字符串解释成JSON再进行扁平化处理         <dependency>             <groupId>com.alibaba< ...

  8. C语言 函数 (库函数 · 自定义函数 · 函数参数 · 函数调用 · 嵌套调用链式访问 · 递归)

    文章目录: 一.函数是什么? 二.库函数 2.1 为什么要有库函数? 2.2 如何学习库函数? 2.3 我们就以 strcpy( ) 函数,来参照文档自学一下: 2.4 总结: 三.自定义函数 3.1 ...

  9. 二值化函数cvThreshold()参数CV_THRESH_OTSU的疑惑

    查看OpenCV文档cvThreshold(),在二值化函数cvThreshold(const CvArr* src, CvArr* dst, double threshold, double max ...

最新文章

  1. 上海交大、华为海思提出X-volution,发力网络核心基础架构创新
  2. python 自然语言处理(二) jieba 分词
  3. 信息系统项目管理师-成本效益分析
  4. C#——实现IComparable接口、IComparableT 接口、IComparer接口、IComparerT 接口和ComparerT 类DEMO
  5. matlab修改矩阵元素,怎么修改矩阵中的某些元素 或者简单点说保留矩阵中的元素...
  6. 使用Axure制作App原型的尺寸设置
  7. list steam_在 Steam 中国版上玩单机游戏也会受到防沉迷系统管控
  8. MySQL MVCC 概述
  9. python批量分析表格_Python统计分析execl文件列表值的方法
  10. cookie 操作
  11. 在SQL2008中,如何让id自动生成并自动递增?如何让时间默认生成?
  12. 操作系统实验报告-多线程编程解决进程间同步和互斥问题
  13. p1957口算题c语言,洛谷P1957口算练习题题解
  14. 数据库第6章总结——关系数据理论
  15. 服务器主板重装系统,简单几步教你如何重新安装系统
  16. Hark的数据结构与算法练习之计数排序
  17. uvm学习笔记----适合新手快速学习
  18. jupyter安装使用
  19. 今天没有收到农行的笔试通知
  20. 粒子群算法求解四维病态方程

热门文章

  1. python模型训练框架_Pytorch-Transformers 1.0发布,支持六个预训练框架,含27个预训练模型...
  2. 启动失败_启动失败了?
  3. typechoSQLIte转MySQL_Typecho SQLite与MySQL的数据库切换及解决MySQL连接打开缓慢问题
  4. 对比原生Node封装的Express路由 和 express框架路由
  5. C语言日期字符串减少两天,C语言第二天(字符串)
  6. 初级c 语言题库,初级计算机考试题库
  7. php资源文件html,nginx 同一域名下分目录配置显示php,html,资源文件
  8. 猎人能单拿修理机器人图纸_南京创新周麒麟行:他们为铁路配备“体检”机器人...
  9. java spring 登录验证_浅析Spring Security登录验证流程源码
  10. 20200316:H指数(leetcode274)