js函数的伪重载
这也是今天写东西是遇到的一个问题,导致我联想起了函数重载的问题。
在javascript中是没有函数重载机制的,对于用惯了java开发的同学可能就表示吃惊了,我屮艸芔茻,函数
没有重载?那怎么搞?!!
从我今天遇到的问题说起吧,还是那个list页面,看过之前刚写的博客的可能知道,我在list页面写了search(order)
函数来执行查询跳转,但是这个页面很特殊,因为导航栏上面也是有一个搜索功能框的,我将那个功能框的搜索
函数设定为search(),接下来好玩的事情发生了:
我从主页面的导航搜索(两个查询参数from和to)进入到结果页(list页面),然后再次点击list页面上面的导航搜索
这时候,跳转的路径多了好多查询参数,这绝壁是执行了list页面的搜索啊,没有执行导航搜索函数search(),并且
地址栏上面 order=undefined,这就更加确定是执行了搜索页的搜索函数(因为只有这个函数才会在路径中拼order参
数),然后一看函数名:一个叫search(order),一个叫search();好像明白了点什么。
下班回家,写了个页面测试(刚刚写的):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div onclick="say('tt');" style="width:200px;height:200px;border:1px solid;">用户可以看到的</div>
<script>
function say(word){
alert(word);
};
function say(){
alert("hello world");
};
</script>
</body>
</html>
点击,弹出“hello world”,函数申明换个顺序亦或是调用函数的时候去除函参,都只会执行最后一个函数名为
search()的函数,而不会管到底有没有形参,至此可以说明,javascript是没有函数重载的机制的。
那么这里为什么要说一下js函数的伪重载呢?
1.通过arguments实现的js函数重载
function f(){
var len= arguments.length;
if( == len){
var length = arguments[];
var width = arguments[];
f2(length,width);
}else{
var length = arguments[];
f1(length);
}
}
function f1(length){
alert("高为:"+length);
}
function f2(length,width){
alert("高为:"+length+",宽为:"+width);
}
代码简单明了,不必多言。
2.JQuery之父John Resig写的《secrets of the JavaScript ninja》中js重载实现方法
网上的这个例子有一节代码看半天没看明白,毕竟明天要上班,准备睡觉了,但是!被这个问题困扰着一直睡
不着,于是爬起来去翻JS高程,一年多之前我还很懵懂的时候看了1/3,现在一些细节性的东西全部忘光了。
在我的再三思索和测试下,终于把这种重载的实现原理搞懂了!!!贴一下我的理解:
function addMethod(object, name, fn) {
var old = object[name];
object[name] = function() {
if(fn.length === arguments.length) {
return fn.apply(this, arguments);
} else if(typeof old === "function") {
return old.apply(this, arguments);
}
}
}
这个函数是为一个对象添加重载方法的。首先来看添加的第一个重载方法(先申明一个对象供后续的重载方法
操作数据):
var people = {
values: ["Dean Edwards", "Alex Russell", "Dean Tom"]
};
①无参数的重载方法
addMethod(people, "find", function() {
return this.values;
});
我们来看看这个函数的执行过程:
var old = people["find"];
people["find"] = function(){
if(function(){return this.values;}.length === arguments.length){
return function(){return this.values;}.apply(this,arguments);
}else if(typeof old === "function"){
return old.apply(this, arguments);
}
}
②一个参数的重载方法
addMethod(people, "find", function(firstName) {
var ret = [];
for(var i = ; i < this.values.length; i++) {
if(this.values[i].indexOf(firstName) === ) {
ret.push(this.values[i]);
}
}
return ret;
});
第三个参数的函数体过长,就不全写了
var old = people["find"];
people["find"] = function(){
if(firstName.length === arguments.length){
return firstName.apply(this,arguments);
}else if(typeof old === "function"){
return old.apply(this, arguments);
}
}
③n个参数的情况,就不介绍了~~
④执行的时候
这里我们分两种情况:执行两个参数的,执行一个参数的;
其实这里重载方法一直写下来,people的find属性到最后还是只有一个的,就是最后那一个,只不过,不知道你
注意到没,每次定义重载方法的时候,都会先将原本的方法拿到并赋值给一个变量old,然后存在else里返回,注
意,此处我用了“存”这个字眼,个人感觉这个做法实在是太绝妙了,如此嵌套有效地避免了多次定义属性值导致
的重载方法覆盖的问题。
按照上面的添加方法顺序,最后的people的find属性应该是这样的(多次添加以此类推):
people["find"] = function(){
if(firstName.length === arguments.length){
return firstName.apply(this,arguments);
}else if(typeof function(){
if(function(){return this.values;}.length === arguments.length){
return function(){return this.values;}.apply(this,arguments);
}else if(typeof old === "function"){
return old.apply(this, arguments);
}
} === "function"){
return function(){
if(function(){return this.values;}.length === arguments.length){
return function(){return this.values;}.apply(this,arguments);
}else if(typeof old === "function"){
return old.apply(this, arguments);
}
}.apply(this, arguments);
}
}
如果执行 people.find("Dean") ,注意这个 arguments.length = 1,和firstName.length(函数支持输入的参数数量,很明显是1)
相等,于是执行第一个if条件里的内容,将参数 "Dean" 作为firstName函数的函参执行函数,也就是第二个重载方法;
如果执行 people.find(),注意这个 arguments.length = 0,就进行else的判断,很显然else判断成立,返回
function(){
if(function(){return this.values;}.length === arguments.length){
return function(){return this.values;}.apply(this,arguments);
}else if(typeof old === "function"){
return old.apply(this, arguments);
}
}.apply(this, arguments);
该语句将arguments作为参数执行函数,我们继续看这个函数:
if(function(){return this.values;}.length === arguments.length){
return function(){return this.values;}.apply(this,arguments);
}else if(typeof old === "function"){
return old.apply(this, arguments);
}
这个函数又进行一次判断,这次判断,很显然if条件成立(这个arguments是一直贯穿整个过程的),于是最终执行:
return this.values;
这个this指向谁?当然是最开始的people咯,于是当无参数时,最终返回people.values!!!
我认为这种方法处理重载,最大的亮点就是刚才说到的 var old = people["find"];以及将它放在else里面执行!
js函数的伪重载的更多相关文章
- 原生js函数的伪重载
一.我们在学习java的时候,其中方法有一个比较的重要的特性重载,根据传入的参数的个数来执行不同的方法,而方法其根据签名来判断,而JavaScript却不能根据方法的签名来进行重载,只能通过参数的个数 ...
- __call PHP伪重载方法
为了避免当调用的方法不存在时产生错误,可以使用 __call() 方法来避免.该方法在调用的方法不存在时会自动调用,程序仍会继续执行下去 该方法有两个参数,第一个参数 $function_name 会 ...
- 如何实现JS函数的重载
javascript不能支持函数的重载,如下: function f(length) { alert("高为:"+length); } function f(length,widt ...
- 3.3 js函数
1.函数语法: 函数声明的方式:function 函数名(参数1,参数2-){//函数体;}函数调用:函数名(参数1,参数2-); 函数内不一定都指定返回值. 如果需要指定返回值,可用 return ...
- Js函数function基础理解
正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定 ...
- func_get_arg、func_get_args、func_num_args实现PHP伪重载
今天在看书的时候,发现书上有这么一条:函数重载的替代方法——伪重载 确实,在PHP中没有函数重载这个概念,让很多时候我们无法进行一些处理,甚至有时候不得不在函数后面定义好N个参数在看到了func_ge ...
- js函数动态传参
js函数体内可以通过arguments对象来接收传递进来的参数,利用这一对象属性可以动态传参. function box() { return arguments[0]+' | '+arguments ...
- paip.编程语言方法重载实现的原理及python,php,js中实现方法重载
paip.编程语言方法重载实现的原理及python,php,js中实现方法重载 有些语言,在方法的重载上,形式上不支持函数重载,但可以通过模拟实现.. 主要原理:根据参数个数进行重载,或者使用默认值 ...
- api日常总结:前端常用js函数和CSS常用技巧
我的移动端media html{font-size:10px} @media screen and (min-width:321px) and (max-width:375px){html{font- ...
随机推荐
- mysql left join中where和on条件的区别
left join中关于where和on条件的几个知识点: 1.多表left join是会生成一张临时表,并返回给用户 2.where条件是针对最后生成的这张临时表进行过滤,过滤掉不符合where条件 ...
- 20145302张薇《Java程序设计》第十周学习总结
20145302 <Java程序设计>第十周学习总结 客户端和服务器端功能 客户端程序功能列表: 接收用户控制台输入 判断输入内容是否合法 按照协议格式发送数据 根据服务器端的反馈给出相应 ...
- 20145324 《Java程序设计》第3周学习总结
20145324 <Java程序设计>第3周学习总结 教材学习内容总结 第四章 1.要产生对象必须先定义类,类是对象的设计图,对象是类的实例,建立实例要用new 2.参数名称与对象数据成员 ...
- java第一周学习总结
学号20145336 <Java程序设计>第1周学习总结 教材学习内容总结 java是sun推出的一门高级编程语言,现已经成为web开发的首选语言.他分为三种技术架构,j2ee针对web应 ...
- 前端小炒的win7使用笔记(收藏篇)
收藏篇 此中技巧及使用笔记,大多为冲浪时无意间发现,进而总结,其中种种小超都已一一验证过. 传说中WIN7上帝模式可查看200多项系统设置项目 在桌面创建文件夹,命名为 GodModel.{ED7BA ...
- 2017 ACM/ICPC Asia Regional Shenyang Online array array array
2017-09-15 21:05:41 writer:pprp 给出一个序列问能否去掉k的数之后使得整个序列不是递增也不是递减的 先求出LIS,然后倒序求出最长递减子序列长度,然后判断去k的数后长度是 ...
- MAC OS 命令行使用详解【转】
你可以整天驾驶汽车而不用知道如何修理它们,但是如果你希望当一个维护员,你就需要知道事情是如何运作的.同样的事情也发生在了 Mac OS X 上:你可以一直使用 Mac 而不用知道如何修理它,但是如果你 ...
- php+mysql中文无法检索出数据
将数据库字符集设置为latin,并将字符转码成gb2312 将字符长度打印出来发现:因为latin中一个字符占用2个字节,utf-8中一个字符占用3个字节,这样一来检索的时候就会出现错误 实验过程: ...
- POJ 2299 Ultra-QuickSort(树状数组+离散化)
http://poj.org/problem?id=2299 题意:给出一组数,求逆序对. 思路: 这道题可以用树状数组解决,但是在此之前,需要对数据进行一下预处理. 这道题目的数据可以大到999,9 ...
- Extjs 分页多选的实现
Extjs 版本 6.X 单页面的多选,没有任何问题. 直接使用 Grid的配置项进行绑定即可获取: xtype: 'grid', bind: { selection: '{checkedRecord ...