关于理解重载的深入学习
2016-06-26 23:55
393 查看
在看到《JavaScript高级程序设计》 没有重载 这部分时,想更加深入了解下重载,于是在网上搜集了一些信息,以下是这部分的总结整理:
没有重载:JavaScript函数不能像传统意义上那样实现重载。而在其他语言中,可以为一个函数编写两个定义,只要这两个定义的签名(接受的参数的类型和数量)不同即可。JavaScript函数没有签名,因为其参数是由包含零或多个值得数组来表示的。而没有函数签名真正的重载是不可能做到的。
虽然没有重载,但我们通常可以这样来实现模拟重载:
1判断传入参数的个数
Javascript的每个函数都带有一个仅在这个函数范围内作用的变量——arguments,它是一个包含所有传给函数的参数的伪数组。为什么是伪数组?——你不能修改它,也不能用push来添加新元素等。但是你可以访问其中的元素,并且同时具有.length属性。有了length属性,我们就可以很方便的知道函数传入了几个参数。
function send( message, who ) {
if( arguments.length >= 2 ) {
console.log("你对" + who + "说:" + message);
}
else {
console.log("你对大家说:" + message);
}
}
2判断传入参数的类型
如果我们在函数中并没有提供参数,那么message和who的值一定为'undefined'。我们可以使用typeof
message = 'undefined'来判断是否传入了参数。
function send( message ) {
if( typeof message === 'undefined' ) {
console.log("ERROR:错误的信息内容");
}
else {
console.log("你说:" + message);
}
}
下面是我看到的一种更好的方法,目前还不太能完全理解:
JQuery之父John Resig写的《secrets of the JavaScript ninja》里的一个绝佳巧妙的方法!那种方法充分的利用了闭包的特性!
在介绍这个方法之前,我们先来看看外国人名字组成哈,比如,John Resig,John是first-name,Resig是last-name,就相当于我们的姓名由姓和名组成一样。我们现在有这样的一个需求,有一个people对象,里面存着一些人名,如下:
我们希望people对象拥有一个find方法,当不传任何参数时,就会把people.values里面的所有元素返回来;当传一个参数时,就把first-name跟这个参数匹配的元素返回来;当传两个参数时,则把first-name和last-name都匹配的才返回来。因为find方法是根据参数的个数不同而执行不同的操作的,所以,我们希望有一个addMethod方法,能够如下的为people添加find的重载:
这时候问题来了,这个全局的addMethod方法该怎么实现呢?John Resig的实现方法如下,代码不长,但是非常的巧妙:
现在,我们一起来分析一个这个addMethod函数,它接收3个参数,第一个为要绑定方法的对象,第二个为绑定的方法名称,第三个为需要绑定的方法(一个匿名函数)。函数体的的分析已经在注释里面了。
OK,现在这个addMethod方法已经实现了,我们接下来就实现people.find的重载啦!全部代码如下
没有重载:JavaScript函数不能像传统意义上那样实现重载。而在其他语言中,可以为一个函数编写两个定义,只要这两个定义的签名(接受的参数的类型和数量)不同即可。JavaScript函数没有签名,因为其参数是由包含零或多个值得数组来表示的。而没有函数签名真正的重载是不可能做到的。
虽然没有重载,但我们通常可以这样来实现模拟重载:
1判断传入参数的个数
Javascript的每个函数都带有一个仅在这个函数范围内作用的变量——arguments,它是一个包含所有传给函数的参数的伪数组。为什么是伪数组?——你不能修改它,也不能用push来添加新元素等。但是你可以访问其中的元素,并且同时具有.length属性。有了length属性,我们就可以很方便的知道函数传入了几个参数。
function send( message, who ) {
if( arguments.length >= 2 ) {
console.log("你对" + who + "说:" + message);
}
else {
console.log("你对大家说:" + message);
}
}
2判断传入参数的类型
如果我们在函数中并没有提供参数,那么message和who的值一定为'undefined'。我们可以使用typeof
message = 'undefined'来判断是否传入了参数。
function send( message ) {
if( typeof message === 'undefined' ) {
console.log("ERROR:错误的信息内容");
}
else {
console.log("你说:" + message);
}
}
下面是我看到的一种更好的方法,目前还不太能完全理解:
JQuery之父John Resig写的《secrets of the JavaScript ninja》里的一个绝佳巧妙的方法!那种方法充分的利用了闭包的特性!
在介绍这个方法之前,我们先来看看外国人名字组成哈,比如,John Resig,John是first-name,Resig是last-name,就相当于我们的姓名由姓和名组成一样。我们现在有这样的一个需求,有一个people对象,里面存着一些人名,如下:
var people = { values: ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"] };
我们希望people对象拥有一个find方法,当不传任何参数时,就会把people.values里面的所有元素返回来;当传一个参数时,就把first-name跟这个参数匹配的元素返回来;当传两个参数时,则把first-name和last-name都匹配的才返回来。因为find方法是根据参数的个数不同而执行不同的操作的,所以,我们希望有一个addMethod方法,能够如下的为people添加find的重载:
addMethod(people, "find", function() {}); /*不传参*/ addMethod(people, "find", function(a) {}); /*传一个*/ addMethod(people, "find", function(a, b) {}); /*传两个*/
这时候问题来了,这个全局的addMethod方法该怎么实现呢?John Resig的实现方法如下,代码不长,但是非常的巧妙:
function addMethod(object, name, fn) { var old = object[name]; //把前一次添加的方法存在一个临时变量old里面 object[name] = function() { // 重写了object[name]的方法 // 如果调用object[name]方法时,传入的参数个数跟预期的一致,则直接调用 if(fn.length === arguments.length) { return fn.apply(this, arguments); // 否则,判断old是否是函数,如果是,就调用old } else if(typeof old === "function") { return old.apply(this, arguments); } } }
现在,我们一起来分析一个这个addMethod函数,它接收3个参数,第一个为要绑定方法的对象,第二个为绑定的方法名称,第三个为需要绑定的方法(一个匿名函数)。函数体的的分析已经在注释里面了。
OK,现在这个addMethod方法已经实现了,我们接下来就实现people.find的重载啦!全部代码如下
//addMethod 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方法的重载 */ // 不传参数时,返回peopld.values里面的所有元素 addMethod(people, "find", function() { return this.values; }); // 传一个参数时,按first-name的匹配进行返回 addMethod(people, "find", function(firstName) { var ret = []; for(var i = 0; i < this.values.length; i++) { if(this.values[i].indexOf(firstName) === 0) { ret.push(this.values[i]); } } return ret; }); // 传两个参数时,返回first-name和last-name都匹配的元素 addMethod(people, "find", function(firstName, lastName) { var ret = []; for(var i = 0; i < this.values.length; i++) { if(this.values[i] === (firstName + " " + lastName)) { ret.push(this.values[i]); } } return ret; }); // 测试: console.log(people.find()); //["Dean Edwards", "Alex Russell", "Dean Tom"] console.log(people.find("Dean")); //["Dean Edwards", "Dean Tom"] console.log(people.find("Dean Edwards")); //["Dean Edwards"]
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 最后一次说说闭包
- Ajax
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 对一个分号引发的错误研究
- 异步流程控制:7 行代码学会 co 模块
- ES6 走马观花(ECMAScript2015 新特性)
- JavaScript拆分字符串时产生空字符的原因
- Canvas 在高清屏下绘制图片变模糊的解决方法
- Redux系列02:一个炒鸡简单的react+redux例子
- JavaScript 各种遍历方式详解
- call/apply/bind 的理解与实例分享