Skip to content

如何使用 js,TS 实现函数重载

C++机制

C++ 语言中的一个重要特性,它允许使用相同的函数名声明多个函数,只要这些函数的参数列表不同,即可实现不同的功能。

上个 c++代码:

c++
#include <iostream>
std::string fn(const std::string& name) {
    return "我是" + name;
}
std::string fn(const std::string& name, int age) {
    return "我是" + name + ", 我" + std::to_string(age) + "岁了!";
}
int main() {
    std::cout << fn("KingKe") << std::endl; // 我是KingKe
    std::cout << fn("KingKe", 30) << std::endl; // 我是KingKe,我30岁了!
    return 0;
}

在此处 C++会直接函数重载通过不同调用方式来输出不同结果。

TS 实现

接下来看一下TS的实现过程

typeScript
function fn(name: string): string; // 方法头 无方法体
function fn(name: string, age?: number): string {
  if (age !== undefined) {
    return `我是${name},我${age}岁了!`;
  } else {
    return `我是${name}!`;
  }
}
fn("KingKe") // 我是KingKe
fn("KingKe",30) // 我是KingKe,我30岁了!

TS 实现重载方法主要是通过一个没有 函数体方法头 来实现。

js 实现

那么 问题来了 这个函数重载 JS 要 怎么来实现呢?

我就立马想到了一个东西 arguments.length

然后就到了这个写法

javascript
function fn() {
  switch (arguments.length) {
    case 1:
      var [name] = arguments;
      return `我是${name}`;
      break;
    case 2:
      var [name, age] = arguments;
      return `我是${name},今年${age}岁`;
      break;
  }
}

fn("KingKe"); // 我是KingKe
fn("KingKe", 30); // 我是KingKe,我30岁了!

提示

但是这个写法感觉好蠢

然后我找到了其他的写法 jQuery 之父 John Resig 写在 《secrets of the JavaScript ninja》 中,这种方法充分的利用了闭包的特性!

javascript
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(window, "fn", (name) => `我是${name}`);
addMethod(window, "fn", (name, age) => `我是${name},今年${age}岁`);
addMethod(
  window,
  "fn",
  (name, age, sport) => `我是${name},今年${age}岁,喜欢玩${sport}`
);

window.fn("KingKe"); // 我是KingKe
window.fn("KingKe", 30); // 我是KingKe,我30岁了!
window.fn("KingKe", 30, "台球"); // 我是KingKe,我30岁了,喜欢玩台球