参考文章:https://www.cnblogs.com/yugege/p/5539020.html
Javascript高级编程学习笔记(16)—— 引用类型(5) Function类型
这一切的根源就是:JS中的函数名只是一个指针,而不是一个函数签名
所以当我们在JS中声明同名函数的时候,实际上就是让已经指向一个函数的指针指向另外一个函数,自然也就不能实现重载了
在《JavaScript高级程序设计》第三版(P66)准确描述了JS没有重载
重载就是一组具有相同名字、不同参数列表的函数(方法)。
模拟重载:
实现方法一:
原理:在函数中判断数组arguments.length,根据传入参数的长度,经由switch判断,然后执行不同的代码。
function overLoading() { // 根据 arguments.length 判断 switch (arguments.length) { case 0: /* 传入0个参数时执行的代码 */ break; case 1: /* 传入1个参数时执行的代码 */ break; case 2: /* 传入2个参数时执行的代码 */ break; /* 还有好多······ */ } }
实现方法二:
思路:实现object.find方法,当传入方法的参数不同时,执行不同的函数,这时就需要动态封装object.find的方法了
demo:有一个people对象,里面存着一些人名。
var people = { values: ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"] };
需求:想要在people对象中拥有一个find方法:
当不传入参数时,返回people.values所有的元素;
当传入一个参数时,就把first-name跟这个参数匹配的元素返回来;
当传入俩个参数时,把first-name和last-name都匹配返回;
addMethod(people, "find", function() {}); /*不传参*/ addMethod(people, "find", function(a) {}); /*传一个*/ addMethod(people, "find", function(a, b) {}); /*传两个*/
那么实现这个addMethod方法?
function addMethod(object, name, fn) { var old = object[name]; // 使用临时变量接收 object 的 name 方法 object[name] = function () { // 定义name方法 /* this 指向 object fn.length 指 fn参数的长度 arguments.length 指得是name()方法中的参数 // 当调用不同参数的fn时,会每次匹配所有的fn,发生递归 */ if(fn.length === arguments.length) { return fn.apply(this, arguments); } else if (typeof old === "function") { return old.apply(this, arguments); } }
测试:
//addMethod function addMethod(object, name, fn) { var old = object[name]; object[name] = function () { console.log(fn.length); console.log(arguments.length); console.log(typeof old); 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++) { console.log(firstName + " " + lastName); 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"]