方法重载(overload)在传统的静态类型语言中是很常见的。JavaScript 作为动态语言, 是没有重载这一说的。一是它的参数没有类型的区分,二是对参数个数也没有检查。虽然语言层面无法自动进行重载,但借助其动态的特性,我们可以在代码中手动检查入参的类型,或者通过 arguments 获取到参数个数,从而实现根据不同的入参做不同的操作。
比如有一个获取聊天消息的方法,根据传入的参数从数组中查找数据。如果入参为数字,则认为是 id,然后从数据源中找对应 id 的数据并返回,否则当成类型,返回这一类型的消息。
function getMessage(query) {
if (typeof query === "nunber") {
return data.find(message => message.id === query);
} else {
return data.filter(message => message.type === query);
}
}
TypeScript 中,假如我们的消息数据为如下结构:
type MessageType = "string" | "image" | "audio";
type Message = {
id: number;
type: MessageType;
content: string;
};
上面获取数据的方法等价于:
function getMessage(
query: number | MessageType
): Message[] | Message | undefined {
if (typeof query === "number") {
return data.find(message => message.id === query);
} else {
return data.filter(message => message.type === query);
}
}
这样做一是类型书写上比较丑陋,二是没有发挥出 TypeScript 类型检查的优势,这里我们是可以根据入参的类型明确知道返回的类型的,即如果传入的是 id,返回的是单个数据或undefined ,如果是根据类型查找,返回的是数组。而现在调用方法后,得到的类型太过宽泛,这和使用 any 做为返回没多大差别。

函数返回类型不够紧凑
因为类型的不明朗,返回的结果都不能直接操作,需要进行类型转换后才能继续。
const result1 = getMessage("audio");
/** 不能直接对 result1 调用数组方法 */
console.log((result1 as Message[]).length);
const result2 = getMessage(1);
if (result2) {
/** 不能对 result2 直接访问消息对象中的属性 */
console.log((result2 as Message).content);
}
重载的实现
这时候可通过提供多个函数类型的声明来解决上面的问题,最后得到的结果就是间接实现了函数的重载。当然这个重载只是 TypeScript 编译时的。
function getMessage(id: number): Message | undefined;
function getMessage(type: MessageType): Message[];
function getMessage(query: any): any {
if (typeof query === "number") {
return data.find(message => message.id === query);
} else {
return data.filter(message => message.type === query);
}
}
这样改造后,我们在调用的时候直接就会有重载的提示。

实现 TypeScript 的重载后调用时的自动提示
并且得到的结果类型是重载方法中指定的入参与返回的组合,在对结果进行使用时,无须再进行类型转换。
const result1 = getMessage("audio");
/** ✅ 无须类型转换 */
console.log(result1.length);
const result2 = getMessage(1);
if (result2) {
/** ✅ 无须类型转换 */
console.log(result2.content);
}
这里需要理解的是,上面添加的函数类型仅作为 TypeScript 在编译时使用的,它不是真的实现像传统静态类型语言那样的重载,也不会改变编译后代码的输出。实际运行时仍然是不带重载的 JavaScript 版本。
编译后的代码
"use strict";
var data = [
{
id: 0,
type: "string",
content: "hello"
},
{
id: 1,
type: "image",
content: "url_for_iamge"
},
{
id: 2,
type: "string",
content: "world"
}
];
function getMessage(query) {
if (typeof query === "number") {
return data.find(function (message) { return message.id === query; });
}
else {
return data.filter(function (message) { return message.type === query; });
}
}
var result1 = getMessage("audio");
/** ✅ 无须类型转换 */
console.log(result1.length);
var result2 = getMessage(1);
if (result2) {
/** ✅ 无须类型转换 */
console.log(result2.content);
}
但这一点也不影响我们在 TypeScript 中使用这种假的重载。
可选参数
另一个 TypeScript 重载的场景。还是上面获取消息数据的方法,因为根据类型查找消息时,会返回同类型消息的一个数组。此时我们想加一个参数实现只返回结果中前几个数据,那么可以很方便地进行如下的改造:
function getMessage(id: number): Message | undefined;
+function getMessage(type: MessageType, count?: number): Message[];
+function getMessage(query: any, count = 10): any {
if (typeof query === "number") {
return data.find(message => message.id === query);
} else {
+ return data.filter(message => message.type === query).splice(0, count);
}
}
通过重载,这个新增的参数很容易实现只针对入参 MessageType 时,这样如果我们有如下的调用,会得到编译时的报错:
/**
- JavaScript中的方法重载
对js有些了解的人都知道,在js中根本就不存在像C#中的那种方法重载,而有的只是方法的覆盖,当你在js中敲入两个或多个同名的方法的时候,不管方法(函数)的参数个数怎么个不同,这个方法名只能属于最后定义 ...
- paip.编程语言方法重载实现的原理及python,php,js中实现方法重载
paip.编程语言方法重载实现的原理及python,php,js中实现方法重载 有些语言,在方法的重载上,形式上不支持函数重载,但可以通过模拟实现.. 主要原理:根据参数个数进行重载,或者使用默认值 ...
- dubbo中Hessian方法重载问题处理
dubbo中Hessian方法重载,报出如下错误信息: 十一月 , :: 下午 org.apache.catalina.core.StandardWrapperValve invoke 严重: Ser ...
- java中的方法重载与重写以及方法修饰符
1. 方法重载Overloading , 是在一个类中,有多个方法,这些方法的名字相同,但是具有不同的参数列表,和返回值 重载的时候,方法名要一样,但是参数类型和参数个数不一样,返回值类型可以相同,也 ...
- Java中的方法重载
一.什么是方法重载? 方法重载就是两个或多个方法的方法名相同,但是方法的形参类型,数量,顺序不同. 上面提到的三点也就是一个方法的特征标,只要有一点不相同,则该方法就不相同,就可以实现重载. 在这里的 ...
- 如何区分Java中的方法重载和重写
首先说的是重载: 方法的重载 * 在同一个类中,方法名相同,参数列表不同.与返回值类型无关. * 参数列表不同: * A:参数个数不同 * B:参数类型不同 * C:参数的顺序不同(不算重载 报错) ...
- java中的方法——重载yu重写(转)
重载(Overloading) (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型. 重载Overloading是一个类中多态性的一种表现. ...
- java中的方法重载(overload)
什么时候方法重载:当两个方法的功能是相似的,可以考虑使用方法重载.若两个方法根本没有关系,无必要使用方法重载. 什么时候代码会发生方法重载:三个条件:1,在同一个类中.2,方法名相同.3,参数列表相同 ...
- 062、Java中的方法重载
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
随机推荐
- js判断对象是否为空
/** *判断对象是否为空 * * @param e * @returns {Number} */function isEmptyObject(e) { var t; for (t in e) ret ...
- CAD中用户选择实体
在CAD的很多操作中都会有需要用户选择实体的时候,这里将我最近项目中用到的方法分享一下,程序原意是希望用户选择一个单行文本或者多行文本,并返回所选文本的内容,直接上代码: CString CPaint ...
- BZOJ_1098_[POI2007]办公楼biu_链表优化BFS
BZOJ_1098_[POI2007]办公楼biu_链表优化BFS Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号 ...
- 实验吧——隐写术之复杂的QR_code
好久没有更新隐写术方面的题目了,对不起各位小可爱,今天我会多多更新几篇文章,来慰藉你们! 永远爱你们的 ---------新宝宝 1:复杂的QR_code 解题思路:保存图片之后使用在线解码工具,并没 ...
- 前端教程(1)http协议的深刻理解
一 HTTP协议简介 作为学习前端开发的开始,我们必须搞明白以下几件事 1.什么是互联网 互联网=物理连接介质+互联网协议 2.互联网建立的目的? 数据传输打破地域限制,否则的话,我 ...
- 大数据技术之_19_Spark学习_03_Spark SQL 应用解析 + Spark SQL 概述、解析 、数据源、实战 + 执行 Spark SQL 查询 + JDBC/ODBC 服务器
第1章 Spark SQL 概述1.1 什么是 Spark SQL1.2 RDD vs DataFrames vs DataSet1.2.1 RDD1.2.2 DataFrame1.2.3 DataS ...
- Bootstrap优秀模板-Unify.2.6.2
这是一个非常老牌的Bootstrap商业模板,全面性和稳定性俱佳,有LandingPage.BussinessPage.AdminPage多种模式,非常推荐用来构建官网.响应式应用Web.管理端Web ...
- 对抗明文口令泄露 —— Web 前端慢 Hash
(更新:https://www.cnblogs.com/index-html/p/frontend_kdf.html ) 0x00 前言 天下武功,唯快不破.但在密码学中则不同.算法越快,越容易破. ...
- Airtest 快速上手教程
一.Airtest 简介: AirtestIDE 是一个跨平台的UI自动化测试编辑器,适用于游戏和App. 自动化脚本录制.一键回放.报告查看,轻而易举实现自动化测试流程 支持基于图像识别的 Airt ...
- .NET中的状态机库Stateless
标题:.NET中的状态机库Stateless 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/10674018.html 介绍 什么是状态机和状态模式 ...
|