ES6 函数扩展
1、ES6可以给函数指定默认参数
ES6之前给函数参数设置默认值:↖(ω)↗
function foo(x, y){
y = y || 'default';
console.log(x, y);
}
foo("my')// my default
foo("my","default") // my default
foo("my",false) //my default //赋值不起作用
foo("my",true)// my true
foo("my","")//my ""
但这有个问题,如果y被赋值了,但是对应的布尔值为false, 则该赋值不起作用。
如上面代码的最后一行打印, y = ''||'default' 会把 默认值设置为 ''(空字符),这样默认值被改
为了避免这个问题,通常需要先判断y是否被赋值。如果没有再等于默认值。
function bar(x,y){
if(typeof y === 'undefined'){
y = 'default'
}
console.log(x, y)
}
bar("my") //undefined
bar("my","")// my "" 这个结果是符合预期的
ES6 给函数指定默认参数, 语法很简洁
function foo(x, y = 'default'){
console.log(x, y)
}
还有亮点好处:
1、阅读代码的人可以立即意识到哪些参数是可以省略的。
2、有利于将来代码的优化,即使未来的版本在对外接口中,彻底拿掉这个参数,也不会导致以前的代码无法运行。
参数变量默认是声明的,在函数体内不能用let 或 const 再次声明
function foo(x = 5) {
let x = 1; // error
const x = 2; // error
}
使用参数默认值时,函数不能🈶️同名参数
// 不报错
function foo(x, x, y) {
// ...
}
同名的参数会是被最后的赋值
foo(1,2,3)// 2,2,3
// 报错
function foo(x, x, y = 1) {
// ...
}
// SyntaxError: Duplicate parameter name not allowed in this context
2、与解构赋值默认值结合使用
只使用 对象的解构赋值默认值,没有使用函数参数的默认值,这种情况下,只有当函数foo的参数是一个对象时,变量x 和 变量y才会通过解构赋值生成。例如,foo(), 参数为空时,调用报错
function foo({x, y = 5}){
console.log(x, y)
}
foo({})// undefine 5
foo({x:1}) // 1 5
foo({x:1, y:2}) //1 2
foo() // TypeError: Cannot read property 'x' of undefined
避免方法
function foo({x, y = 5} = {}){
console.log(x, y)
}
foo() // undefined 5
再例如:
function fetch(url, { body = '', method = 'GET', headers = {} }) {
console.log(method);
}
fetch('http://example.com', {})
// "GET"
fetch('http://example.com')
// 报错
需要给解构赋值 指定默认参数
function fetch(url, { body = '', method = 'GET', headers = {} } = {}) {
console.log(method);
}
fetch('http://example.com')
// "GET"
练习
// 写法一
function m1({x = 0, y = 0} = {}) {
return [x, y];
}
// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
上面两种写法都对函数的参数设定了默认值,区别是写法一函数参数的默认值是空对象,但是设置了对象解构赋值的默认值;写法二函数参数的默认值是一个有具体属性的对象,但是没有设置对象解构赋值的默认值。
参数默认值最好在参数表的结尾设置
因为函数调用时,无法省略有默认值的参数,否则会报错。
3、函数的length 属性
表示没有指定默认值的参数的个数。length 的含义是,函数预期传入的参数个数,有了默认值就不用调用者传递了
但是,如果设置的默认值的参数不是尾参数,那么length 属性也不再计入后面的参数了。
4、作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
上面代码中,参数y的默认值等于变量x。调用函数f时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x指向第一个参数x,而不是全局变量x,所以输出是2。
let x = 1;
function f(y = x) {
let x = 2;
console.log(y);
}
f() // 1
上面代码中,函数f调用时,参数y = x形成一个单独的作用域。这个作用域里面,变量x本身没有定义,所以指向外层的全局变量x。函数调用时,函数体内部的局部变量x影响不到默认值变量x。