es6的函数可以定义多个可选参数吗?

es6的函数可以定义多个可选参数吗。比如

function sayHello(a:string, b?:string, c?:string){

}

我觉得是不可以的,但看到项目中有这么写的

阅读 3.6k
6 个回答

对 ES5 而言,所有的参数都是可选参数,反而是必选参数的约束要靠开发者自己实现;
ES6 提供了默认参数,比 ES5 进步了不少,但由于 ES6 是向下兼容 ES5 的(ES6 运行时可以运行按照 ES5 标准写的旧代码),所以实际上 ES6 函数所有的参数也还是全部可选,对参数的约束仍旧是靠开发者自己实现;
真正有“必选参数+可选参数”概念的,是 TS ,TS 对可选参数的静态约束是“可选参数不能放在必选参数前面”,只要符合这个约束即可,对可选参数的数量则不作约束。
还有一个函数 CanvasRenderingContext2D.prototype.drawImage 就是非常典型的多可选参数函数,其重载让人眼花缭乱:

drawImage(image:ImageLike, dx:number, dy:number):void;
drawImage(image:ImageLike,  dx:number, dy:number, dWidth:number, dHeight:number):void;
drawImage(image:ImageLike, sx:number, sy:number, sWidth:number, sHeight:number, dx:number, dy:number, dWidth:number, dHeight:number):void;

另外,常见 JS 运行时提供的一些函数,比如Array.prototype.pushMath.maxconsole.logsetTimeout等都是有不限数量的可选参数的。

对于 JS 来说,所有参数都是可选。可以定义一堆参数,但是调用函数的时候一个都不传

function test(a, b, c) {
    console.log(a);
    console.log(b);
    console.log(c);
}

test();        // 会输出三个 undefined

所以使用 JS 的时候需要自己在程序里去判断参数是否有效(甚至需要判断是否是预期的类型)

而题主给的 sayHello 并不是 JS 代码,这是声明了类型的,是 TS 代码。TS 在 JS 的语法基础上进行了更为严格的约束,比如 sayHello 就约束了每个参数都是 string 类型,其中第 1 个参数必须,后两个可选。

如果一个参数都不给,TSC 会报错,告诉你需要 1~3 个参数

image.png

甚至你想多给几个参数都不行

image.png

这些约束都是 TS 的,不是 JS(ES) 的。在完全 TS 环境下,实现 sayHello 可以完全不考虑参数的合法性问题,声明了 astring 那它就一定存在,而且是 string 类型,不可能是 null 或者 undefined。声明了 b?: string,那说明 b 一定是 string 类型,但有可能不传,也就是 undefined(可选参数实际上都会加 undefined 类型),使用时只需要对 undefined 的情况进行判断。因此可以在实现的时候少写很多用于判断类型和容错的代码。

但刚才提到了是在完全 TS 环境下。如果这段代码编译成了 JS 在其他地方使用,仍然会存在参数不安全的情况。

在JS(无论ES6以上还是以下)里,函数被调用时,并不会检查传入的参数数量是否符合定义时的数量。
所以利用这个特性,JS可以实现任意数量的可选参数

比如定义function func(a, b, c, d),你用func(1, 2, 3, 4)func(1, 2, 3)func(1, 2)func(1) 甚至func()都是合法的。此时缺失的参数,在函数体内的值为undefined

ES6中的函数是可以定义多个可选参数的。具体来说,ES6中定义函数时可以使用函数参数的默认值来实现多个可选参数,如果调用函数不传递该参数,则该参数的值将为默认值。举个例子

function exampleFunc(param1, param2 = 'default1', param3 = 'default2') {
  console.log(param1, param2, param3);
}

exampleFunc('value1'); // 输出: value1 default1 default2
exampleFunc('value1', 'value2'); // 输出: value1 value2 default2
exampleFunc('value1', 'value2', 'value3'); // 输出: value1 value2 value3

你这个是 typescript 的写法,是可以的,b 和 c 都是可传可不传,所以有以下几种调用方式:

sayHello(a);
sayHello(a, b);
sayHello(a, b, c);

另外,如果想只传 c 可以这么写,不传和传 undefined 是等价的:
sayHello(a, undefined, c);
但是一般不建议这么处理,建议把 b c 合起来作为一个 options 对象之类的可选属性进行传递

推荐问题
logo
Microsoft
子站问答
访问
宣传栏