• js之重载


    在面向对象语言中, 重载就是一组具有相同名字、不同参数列表的函数,但在js中,重载的实现不能像js一样那么简单,因为js名字相同的函数会相互覆盖,这样只能输出最后一个同名函数,哪怕参数不一样,那我们怎样才能做到重载呢,

    首先我们可以利用js的函数中一个参数,arguments,该参数有个属性,length, 根据参数组的长度不同,我们可以做出相应的动作,从而达到重载的目的

    function add(){
                var len = arguments.length;        
                var a = arguments[0];
                var b = arguments[1];
                var c = arguments[2];
                switch(len){
                    case  1:
                         
                         console.log(a);
                         break;
                    case  2:
                                            
                          console.log(a+b);
                          break;
                    case  3:
                        
                          console.log(a+b+c);
                         break;    
                    default:
                          break;
                               
                }
            }
            add(1); //1
            add(1,2); //3
            add(1,2,3); // 6

    如上面的代码,如果我们将add 函数传进来的参数进行判断,如果与条件相符,我们就做出相应的动作,这种方法通俗易懂,如果以后面试问道重载可以回答一下,但这样代码的利用性太低,多个函数需要重复多次,我们下面讲一个JQuery之父John Resig写的重载

        function addMethod(object, name, fn) {
                  var old = object[name]; 
                  object[name] = function() {
                        console.log(arguments);
                        console.log(fn.length);
                    if(fn.length === arguments.length) {
                      return fn.apply(this, arguments);
                    } else if(typeof old === "function") {
                      return old.apply(this, arguments);
                    }
                  }
                   console.log(object[name]);
                }

    这是一个关键的方法,他有三个参数,第一个是指定的对象,第二个是指定对象要重载的方法,第三个是实际重载方法中要执行的方法,这样说有点绕口,下面来看代码

    var people = {
                  values: ["Dean Edwards", "Alex Russell", "Dean Tom"]
                };
                 
             
                addMethod(people, "find", function() {
                  return this.values;
                });
    // 这里进行第一次函数绑定,对people这个对象进行绑定find函数,我们根据上面的代码可知,此时的old 为undefined
    此时的people.find()被构造成一下函数

    function() {
                        console.log(arguments);
                        console.log(fn.length);
                    if(fn.length === arguments.length) {
                      return fn.apply(this, arguments);
                    } else if(typeof old === "function") {
                      return old.apply(this, arguments);
                    }
                  }

    
    

     然后我们进行第二次绑定

        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;
                });

    此时进行绑定时,old 变量这时候就变为了第一个people.find();函数,那么下次被调用时,第一个addMethod所绑定的people.find()函数就会存在内存中,这里巧妙的利用了闭包,将三个find函数保存在不同的内存空间中,其中的old变量会指向上一个的people.find函数

    从而,一直往上访问,知道访问到第一个的old ,下面是完整的代码。

    function addMethod(object, name, fn) {
                  var old = object[name]; 
                  object[name] = function() {
                        console.log(arguments);
                        console.log(fn.length);
                    if(fn.length === arguments.length) {
                      return fn.apply(this, arguments);
                    } else if(typeof old === "function") {
                      return old.apply(this, arguments);
                    }
                  }
                   console.log(object[name]);
                }
                 
                 
                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"]*/

    当我们调用people.find();时会首先在addMethod所绑定的第三个people.find()中寻找,此时,fn.length就是期望函数的参数,而arguments.length是我们调用函数的参数,第一个调用函数的参数为0;而第三个所绑定的find函数参数为2个,所以不相等,我们就会向上找

    old的所指向的第二个绑定函数,以此类推,直到找到与之相匹配的,然后就用apply函数改变调用函数的上下文,并且传入相关参数进行输出。

  • 相关阅读:
    编译错误
    __attribute__
    strcmp-sse2-unaligned.S: No such file or directory.
    boost多线程编译出错
    QByteArray与QString的互相转换
    ffplay播放黑广播的声音
    ./configure详解
    linux发行版安装vmci.sys版本错误
    linux命令
    open函数的打开标志所在文件
  • 原文地址:https://www.cnblogs.com/maoxiaodun/p/10021609.html
Copyright © 2020-2023  润新知