资讯专栏INFORMATION COLUMN

JavaScript实现函数重载

QLQ / 1771人阅读

摘要:我们知道,函数可以随意传递任意数量任意类型的参数,那么它有没有重载呢答案是有的,下面我们通过种方法来实现的函数重载。因此,每次调用,都会有一个执行环境保存着当时的和,所以在调用的时候可以找到当时注入的,实现函数重载。

概念

重载是指函数或者方法有相同的名称,但是参数个数或类型不相同的情形,这样的同名不同参的函数或者方法之间,互相称之为重载函数或方法。

我们知道,JavaScript函数可以随意传递任意数量、任意类型的参数,那么它有没有重载呢?

答案是有的,下面我们通过3种方法来实现JavaScript的函数重载。

实现 0. 目标

我们有一个people对象

var people = {
  values: ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"]
};

想要实现一个find方法,不传参数的时候,输出所有名字,只传1个参数的时候,输出所有fristName和参数相同的名字,传2个参数的时候,输出所有firstName和lastName和2个参数分别相同的名字。

people.find();                          // ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"]
people.find("Dean");                    // ["Dean Edwards", "Dean Tom"]
people.find("Dean", "Edwards");            // ["Dean Edwards"]
1. 利用arguments和switch实现重载
people.find = function () {
  switch (arguments.length) {
    case 0:
      return this.values;

    case 1:
      return this.values.filter((value) => {
        var firstName = arguments[0];
        return value.indexOf(firstName) !== -1 ? true : false;
      });

    case 2:
      return this.values.filter((value) => {
        var fullName = `${arguments[0]} ${arguments[1]}`;
        return value.indexOf(fullName) !== -1 ? true : false;
      });
  }
};

console.log(people.find());                 // ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"]
console.log(people.find("Dean"));           // ["Dean Edwards", "Dean Tom"]
console.log(people.find("Dean", "Edwards"));   // ["Dean Edwards"]

这种方式大家肯定都能看懂,就不多说啦。

2. 利用arguments和闭包实现重载
function addMethod (object, name, fn) {
  // 把前一次添加的方法存在一个临时变量old中
  var old = object[name];

  // 重写object[name]方法
  object[name] = function () {
    if (fn.length === arguments.length) {
      // 如果调用object[name]方法时,如果实参和形参个数一致,则直接调用
      return fn.apply(this, arguments);
    } else if (typeof old === "function") {
      // 如果实参形参不一致,判断old是否是函数,如果是,就调用old
      return old.apply(this, arguments);
    }
  };
}

addMethod(people, "find", function() {
  return this.values;
});

addMethod(people, "find", function(firstName) {
  return this.values.filter((value) => {
    return value.indexOf(firstName) !== -1 ? true : false;
  });
});

addMethod(people, "find", function(firstName, lastName) {
  return this.values.filter((value) => {
    var fullName = `${firstName} ${lastName}`;
    return value.indexOf(fullName) !== -1 ? true : false;
  });
});

console.log(people.find());                     // ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"]
console.log(people.find("Dean"));               // ["Dean Edwards", "Dean Tom"]
console.log(people.find("Dean", "Edwards"));    // ["Dean Edwards"]

这里addMethod(object, name, fn)方法是核心。我们着重分析一下为什么这里会有闭包,可以保存上一个注册的函数。

function addMethod (object, name, fn) {
  // object, name, fn是传入的3个参数
  var old = object[name];

  object[name] = function () {
    // 这里对old和fn进行了引用
    if (fn.length === arguments.length) {
      return fn.apply(this, arguments);
    } else if (typeof old === "function") {
      return old.apply(this, arguments);
    }
  };
}

object是另外一个引用对象,它的一个方法中引用了old和fn,所以对于addMethod来说,它的局部变量在addMethod函数执行完后,仍然被另外的变量所引用,导致它的执行环境无法销毁,所以产生了闭包

因此,每次调用addMethod,都会有一个执行环境保存着当时的old和fn,所以在调用people.find()的时候可以找到当时注入的fn,实现函数重载。

3. 利用Proxy和arguments实现重载
var proxy = new Proxy(people, {
  get: function (target, key, receiver) {
    if (key === "find") {
      return function () {
        switch (arguments.length) {
          case 0:
            return this.values;
      
          case 1:
            return this.values.filter((value) => {
              var firstName = arguments[0];
              return value.indexOf(firstName) !== -1 ? true : false;
            });
      
          case 2:
            return this.values.filter((value) => {
              var fullName = `${arguments[0]} ${arguments[1]}`;
              return value.indexOf(fullName) !== -1 ? true : false;
            });
        }
      };
    }

    return Reflect.get(target , key , receiver);
  },

  set: function (target, key, value, receiver) {
    return Reflect.set(target, key, value, receiver);
  }
});

console.log(proxy.find());                     // ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"]
console.log(proxy.find("Dean"));               // ["Dean Edwards", "Dean Tom"]
console.log(proxy.find("Dean", "Edwards"));   // ["Dean Edwards"]

这样写其实感觉有点画蛇添足了,就当成是另外一种思路吧。

总结

JavaScript可以实现函数重载,主要有两种思想:

利用arguments类数组来判断接收参数的个数

利用闭包保存以前注册进来的同名函数

欢迎关注我的公众号

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97143.html

相关文章

  • 重名就会被覆盖?那JavaScript中是如何实现重载的呢?

    摘要:但是我们知道中是没有重载的为什么没重载不是的特性也会有的吗,因为后面定义的函数会覆盖前面的同名函数,但是重载那么好用,我们想在实现函数重载该怎么办呢今天就来给大家讲讲在里面实现函数重载的两个思路。这就是闭包的核心作用。 大家都知道,所谓重载,就是一组相同的函数名,有不同个数的参数,在使用时调用一个函数名,传入不同参数,根据你的参数个数,来决定使用不同的函数!重载这个在JAVA这些经典的...

    mozillazg 评论0 收藏0
  • JavaScript函数重载

    摘要:实现函数重载函数重载,是等编程语言中具有的一项特性,这项特性允许创建数项名称相同但输入输出类型或个数不同的子程序,它可以简单地称为一个单独功能可以执行多项任务的能力。其它在中加入了类型,它自带函数重载。 JavaScript实现函数重载 函数重载(function overloading),是 Ada、C++、C#、D、Java等编程语言中具有的一项特性,这项特性允许创建数项名称相同...

    SnaiLiu 评论0 收藏0
  • JavaScript中的函数重载(Function overloading)

    摘要:说明中没有真正意义上的函数重载。先看第一种办法,通过对象来实现对象,是函数内部的一个类数组对象,它里面保存着调用函数时,传递给函数的所有参数。 说明 JavaScript 中没有真正意义上的函数重载。 函数重载 函数名相同,函数的参数列表不同(包括参数个数和参数类型),根据参数的不同去执行不同的操作。 我们举个例子看看 function overload(a){ conso...

    inapt 评论0 收藏0
  • JavaScript函数重载

    摘要:译者按之父巧妙地利用了闭包,实现了函数重载。在一个业余项目中,我写了一个简单的函数,用于实现函数重载。而所谓函数重载,就是函数名称一样,但是输入输出不一样。 译者按: jQuery之父John Resig巧妙地利用了闭包,实现了JavaScript函数重载。 原文: JavaScript Method Overloading 译者: Fundebug 为了保证可读性,本文采用意...

    testHs 评论0 收藏0
  • JavaScript之模拟函数重载

    摘要:背景高级程序设计中提及,不支持函数重载。若出现函数名称相同情况下,后者覆盖前者,故此不会出现重载的情况。维基百科场景例如,一个工厂有着数量级的员工,期望通过姓名找到某一员工或某类员工,使用同一个方法通过透传参数个数去查找员工。 背景        《JavaScript高级程序设计》中提及,JavaScript 不支持函数重载。若出现函数名称相同情况下,后者覆盖前者,故此不会出现重载...

    chenjiang3 评论0 收藏0

发表评论

0条评论

QLQ

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<