函数形参的默认值
在es5中实现默认参数功能
function makeRequest(url,timeout,callback){
timeout = timeout || 2000;
callback = callback || function(){ ... }
...
}
这里有个问题,当timeout传入的值为0时,这个值是合法的,但也会被置位2000,因为0代表false。
继续优化我们上面的方法:
function makeRequest(url,timeout,callback){
timeout = (typeof timeout !== 'undefined') ? timeout : 2000;
callback = (typeof callback !== 'undefined') ? callback : function(){ ... }
...
}
尽管这种方法已经安全的实现了配置参数默认值,但是需要额外的代码来执行这种非常基础的操作。不够简洁!
es6中的默认参数值
直接上代码:
function makeRequest(url,timeout = 2000,callback = function(){}){ ... }
只需在声明函数的形参名称后面通过"="赋予默认值即可。可以为任意参数指定默认值,在已指定默认值的参数后可以继续声明无默认值参数。
tips:null是一个合法值,因此给带有默认值的参数传递null值,该参数的值会设置为null,可简单理解为只有该参数为对应的值为nundefined时,参数的默认值才会生效
默认参数表达式
除了原始类型的值可以作为参数默认值外,非原始值也可以作为参数的默认值:
function getValue(){
return 5;
}
function add(first,second = getValue()){
return first + second;
}
console.log(add(1,1)); //2
console.log(add(1)); //6
tips:初次解析函数声明时不会调用getValue()方法,只有当调用add()函数且不传入第二个参数时才会调用。
正因为默认参数是在函数调用时求值,所以可以使用先定义的参数作为后定义参数的默认值(因为在声明函数时,先定义的参数已经被声明)
function add(first,second = first){
return first + second;
}
console.log(add(1,1)); //2
console.log(add(1)); //2
tips:在引用参数默认值的时候,只允许引用前面参数的值,即先定义的参数不能访问后定义的参数:function add(first=second,second) 这样是会报错误的
处理无命名参数
产生无命名参数的情况:js函数语法规定,无论函数已定义的命名参数有多少,都不限制调用时传入的实际参数数量。
es5中的无命名参数
通过arguments来操作:
function (arg1){
for(let i=1,len=arguments.length;i<len;i++){ //第一个是命名参数,要获取未命名参数需要从arguments[1]开始
process(arguments[i])
}
}
这样可以实现处理多个未命名参数的要求,但是存在几个缺点:
- 并不容易发现这个函数可以接受任意数量的参数
- 因为第一个参数为命名参数,所以获取未命名参数的索引位置应该从1开始。当遇到函数有2个,3个,4个....命名参数时,再处理未命名参数就会疲于计算索引开始位置,显得不灵活
es6的不定参数
es6中,在函数的命名参数前添加三个点(...),就表明这是一个不定参数,改参数为一个数组,包含着自它之后传入的所有参数。
function (...arg){
for(let i=0,len=arg.length;i<len;i++){
process(arg[i]);
}
}
不定参数的使用限制
- 每个函数最多只能声明一个不定参数,而且一定要放在所有参数的末尾
- 不定参数不能用于对象字面量setter中,会导致语法错误,例:
let obj={
set name(...value){
...
}
}
之所以报错是因为setter的参数只能有一个
展开运算符
展开运算符与不定参数很相似。
不定参数可以让你指定多个各自独立的参数,并通过整合后的数组来访问;而展开运算符可以让你指定一个数组,将他们打散后作为各自独立的参数传入函数。
例如有一个需求需要你在一个数组中找出最大的那个数,es5只能用如下方式实现
let values=[25,50,75,100];
console.log(Math.max.apply(Math,values)); //因为Math.max方法不支持接收数组参数,所以只能通过apply的方式来变通解决这个问题
es6解决办法:
let values=[25,50,75,100];
console.log(Math.max(...values)); //简单明了
tips:可以将展开运算符与其它正常传入的参数混合使用:console.log(Math.max(...values,2,55,77));
箭头函数
箭头函数对比普通函数:
- 没有this,super,arguments和new.target绑定,箭头函数中的这些值由外围最近一层非箭头函数决定
- 不能通过new关键字调用。箭头函数没有[[construct]]方法,所以不能被用作构造函数,通过new关键字调用箭头函数,程序会抛出错误
- 没有原型。因为不可以通过new调用箭头函数,因此没有构建原型的需求,所以箭头函数不存在prototype这个属性
- 不可以改变this绑定
- 不支持arguments对象,必须通过命名参数和不定参数这两种形式访问函数的参数
- 不支持重复的命名参数
箭头函数语法
let reflect = value => value; //只有一个参数时可以直接写参数名
let reflect = (value1,value2) => value1 + value2; //有两个参数时需要给参数加小括号
let reflect = () => 5; //没有参数时需要一对空的小括号
let reflect = () => {
process1();
process2();
...
return 5; //当函数体有多条语句时需要花括号包含,如果有返回值,需要显式地return ,函数体只有一条语句时,该语句的执行结果就是默认的返回值
}
let reflect = () => ({name:'zj',age:18}); //当需要return一个对象字面量时需要添加(),已指明这是返回值,而不是函数体 {}的原因
let reflect = ((name) => name;)('zj'); //立即执行函数表达式
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。