JS函数重载的解决方案


Posted in Javascript onMay 13, 2014

在面向对象的编程中,很多语言都支持函数重载,能根据函数传递的不同个数、类型的参数来做不同的操作,JS对它却不支持,需要我们额外做些小动作。


在JS的函数执行上下文中有一个名为arguments的有意思的变量,它以数组的形式存储了函数执行时传递过来的所有参数,即使函数定义没有定义这 么多个形参。还有一个特别之处就是跟Array类型相比,arguments变量有且只有一个length属性,Array的方法,例如push、pop 等,它并不具备,它只是一个“伪数组”:具有length属性,存储的数组能够用数组访问符[]来访问,并且是只读不可写。

一、对于不同个数参数的重载

这里应该很明白,直接用arguments函数的length属性来判断就可以了。

<script type="text/javascript">
function talk(msg,handler){ 
     var len = arguments.length; 
    //传递过来一个参数的时候执行 
    if(len==1){ 
    alert("Function say:"+msg); 
    } 
    //传递过来两个参数的时候执行 
    else if(len==2){ 
         handler(msg); 
     } 
} 
talk("demo"); 
talk("demo",function(w){alert("Handler say:"+w);}); 
</script>

二、对于不同类型的参数的重载 

对于JS这样一种动态类型的语言,这种变量声明的随意性淡化了严格的变量类型在开发人员脑子里的重要性(PS:同样是基于ECMA体系的,AS就引入 了变量声明的强制类型),很多意想不到的BUG其实都是由这种变量类型的自动转换造成的。其实JS提供了很准确的方法让我们来严格检测变量的类型,比较通 用的就是typeof方法和constructor属性。

1、typeof variable 返回变量类型

temp = "say"; //string 
temp = 1; //number 
temp = undefined; //undefined 
temp = null; //object 
temp = {}; //object 
temp = []; //object 
temp = true; //boolean 
temp = function (){} //function 
alert(typeof temp);

    通过上面的测试你可以看出来,对于null,Object,Array返回的都是object类型,而使用下面的方法就可以解决这个困扰。

2.constructor属性检测变量类型

    JS中每个对象都有constructor属性,它是用来引用构造此对象的函数,通过对这个引用的判断就可以检测变量类型了。

temp = "say"; 
temp.constructor==String; //true 
temp= {}; 
temp.constructor == Object;//true 
temp= []; 
temp.constructor == Array;//true

    通过上面的测试已经很容易的把Array和Object类型的变量区分开了。下面我们来对自定义的对象做个测试看看会发生什么。

//自定义对象 
function Ball(){} 
//实例化一个对象 
var basketBall = new Ball(); 
basketBall.constructor==Ball; //true

    这可以说明constructor属性对于自定义的对象一样适用。

在弄清楚了上面两个方法的适用以后再来回到JS函数重载的模拟上来,下面这个例子是根据参数类型来重载。

function talk(msg){ 
     var t = typeof msg; 
     if(t=="string"){ 
            alert("It's a string"); 
    } 
    else if(t=="number"){ 
            alert("It's a number"); 
     } 
} 
talk(10); //It's a string 
talk("demo"); //It's a number

附上一个很巧妙的严格检测参数类型和个数的函数:

//依据参数列表来严格地检查一个变量列表的类型 
function strict( types, args ) { 
     //确保参数的数目和类型核匹配 
     if ( types.length != args.length ) { 
            //如果长度不匹配,则抛出异常 
           throw "Invalid number of arguments. Expected " + types.length + ", received " + args.length + " instead."; 
    } 
    //遍历每一个参数,检查基类型 
    for ( var i = 0; i < args.length; i++ ) { 
          //如JavaScript某一项类型不匹配,则抛出异常 
          if ( args[i].constructor != types[i] ) { 
                throw "Invalid argument type. Expected " + types[i].name +", received " + args[i].constructor.name + " instead."; 
          } 
     } 
} 
//上述方法的使用 
function doFunction(id,name){ 
     //检测参数个数和类型 
     strict([Number,String],arguments); 
  .. 
}
Javascript 相关文章推荐
通过Jscript中@cc_on 语句识别IE浏览器及版本的代码
May 07 Javascript
JavaScript DOM 编程艺术(第2版)读书笔记(JavaScript的最佳实践)
Oct 01 Javascript
jquery根据锚点offset值实现动画切换
Sep 11 Javascript
jQuery Ajax页面局部加载方法汇总
Jun 02 Javascript
js 监控iframe URL的变化实例代码
Jul 12 Javascript
AngularJs每天学习之总体介绍
Aug 07 Javascript
vue自定义指令directive实例详解
Jan 17 Javascript
微信小程序时间轴实现方法示例
Jan 14 Javascript
详解如何提升JSON.stringify()的性能
Jun 12 Javascript
layer弹出层自适应高度,垂直水平居中的实现
Sep 16 Javascript
es6 for循环中let和var区别详解
Jan 12 Javascript
Vue 实现一个简单的鼠标拖拽滚动效果插件
Dec 10 Vue.js
一个JS函数搞定网页标题(title)闪动效果
May 13 #Javascript
JS获得浏览器版本和操作系统版本的例子
May 13 #Javascript
当滚动条滚动到页面底部自动加载增加内容的js代码
May 13 #Javascript
js语法学习之判断一个对象是否为数组
May 13 #Javascript
js中定义一个变量并判断其是否为空的方法
May 13 #Javascript
jQuery 计算iframe 窗口大小的方法
May 13 #Javascript
js 调用百度地图api并在地图上进行打点添加标注
May 13 #Javascript
You might like
PHP面向对象概念
2011/11/06 PHP
php数组函数序列之array_flip() 将数组键名与值对调
2011/11/07 PHP
PHP内核探索:变量概述
2014/01/30 PHP
PHP 5.3新增魔术方法__invoke概述
2014/07/23 PHP
thinkPHP+phpexcel实现excel报表输出功能示例
2017/06/06 PHP
workerman结合laravel开发在线聊天应用的示例代码
2018/10/30 PHP
Laravel5.1框架注册中间件的三种场景详解
2019/07/09 PHP
javascript css float属性的特殊写法
2008/11/13 Javascript
常用Extjs工具:Extjs.util.Format使用方法
2012/03/22 Javascript
jquery获取被勾选的checked(选中)的那一行的3列和4列的值
2013/07/04 Javascript
js时间戳格式化成日期格式的多种方法
2013/11/11 Javascript
jQuery简单实现提交数据出现loading进度条的方法
2016/03/29 Javascript
AngularJS入门教程之Scope(作用域)
2016/07/27 Javascript
js实现移动端微信页面禁止字体放大
2017/02/16 Javascript
利用n工具轻松管理Node.js的版本
2017/04/21 Javascript
BootStrap Table前台和后台分页对JSON格式的要求
2017/06/28 Javascript
原生JS实现简单的倒计时功能示例
2018/08/30 Javascript
基于layPage插件实现两种分页方式浅析
2019/07/27 Javascript
vue 获取到数据但却渲染不到页面上的解决方法
2020/11/19 Vue.js
[38:51]2014 DOTA2国际邀请赛中国区预选赛 Orenda VS LGD-CDEC
2014/05/22 DOTA
[04:27]2014DOTA2国际邀请赛 NAVI战队官方纪录片
2014/07/21 DOTA
Python的垃圾回收机制深入分析
2014/07/16 Python
Python聚类算法之DBSACN实例分析
2015/11/20 Python
基于Python实现通过微信搜索功能查看谁把你删除了
2016/01/27 Python
Queue 实现生产者消费者模型(实例讲解)
2017/11/13 Python
python针对excel的操作技巧
2018/03/13 Python
Python使用matplotlib绘制三维图形示例
2018/08/25 Python
浅谈python连续赋值可能引发的错误
2018/11/10 Python
python opencv 读取本地视频文件 修改ffmpeg的方法
2019/01/26 Python
Python Pandas中根据列的值选取多行数据
2019/07/08 Python
新加坡网上化妆品店:Best Buy World
2018/05/18 全球购物
世界排名第一的万圣节服装店:Spirit Halloween
2018/10/16 全球购物
介绍一下Prototype的$()函数,$F()函数,$A()函数都是什么作用?
2014/03/05 面试题
高三学习决心书
2014/03/11 职场文书
表扬信范文
2015/05/04 职场文书
贷款工资证明范本
2015/06/12 职场文书