发布网友 发布时间:2022-04-26 05:54
共1个回答
热心网友 时间:2022-04-22 15:08
第一,常见的静态类型语言中的overload是发生在编译时的,编译器可以清楚的将每一处同名函数调用对应到你写的不同的函数实现。也就是,同名只是一个(让程序员看到的)假象。如你写了fun(x),有两个实现fun(x: string)、fun(x: int),真正编译后的程序里实际会有两个函数,假设记做fun_string和fun_int,而每个fun(x)调用会被自动替换成fun_string(x)或fun_int(x)。有没有可能编译器无法确定替换成哪一个?当然有可能,这个时候编译器就报错了嘛,意思是你代码写错啦!第二,JavaScript是动态类型,所以是没有上面这种意义上的overload的。但JS程序员可以在运行时判断类型,也就是 function fun(x) { if (typeof x === 'string') ... else/* assume x is int */ ... } 。TypeScript 的『overload』只是允许给这样的函数标注多个类型。某轮说这是『绕过编译器类型检查』,是有问题的。这不是绕过,把函数参数标记为 (x: any) 才叫『绕过』。不过因为函数的具体实现只有一个,代码本身会比上面那种overload要麻烦一些,比如说为了检测类型偶尔你需要自己实现一些 type guard。至于说『下标函数也不能自己写,这个很傻*』,我估计某轮指的是 operator overload,然而很多语言都不允许(比如 java)。所以单单骂 TS/JS 有点扯。第三,TS理论上当然是可以实现传统的 overload 的,比如直接生成两个函数,fun1、fun2。问题是从TS与JS的互操作性上来说,这事情就比较麻烦,比如一个js项目用了ts的库,我不能直接写fun,而得写fun1、fun2。本来 overload 就是希望给程序员提供便利,但现在就并没有什么卵用。其实像java之类有『真』重载的语言编译到js,或直接和js互操作,都有类似的问题。早在二十年前rhino里就有这问题——你在js里要指定到底调用的是哪一个java的重载方法是非常烦人的。特别是构造器,一般函数你说编译成fun_string、fun_int也就算了,但构造器呢?相当棘手。那TS能不能自动生成一个把多个实现合并起来的fun呢?不好办。因为runtime的类型检查和编译时类型检查是很不一样的(可以上网去查下override和overload的差异,前者通常就是runtime的),而且TS编译后并没有保留类型信息,所以复杂一点的类型根本没法在runtime检查。并且不带有runtime类型检查是TS的设计目标确定的,所谓by design是也。(其他答案也都提到了这一点。)