1.函数参数的默认值
(1)基本用法
ES6之前不能直接给函数的参数指定默认值,只能通过变通的方法
function log(x, y) {
y = y || 'World';
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World
ES5允许为函数的参数设置默认值,即直接写到函数定义的后面
function log(x, y = 'World') {
console.log(x, y);
}
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello
ES6写法的优点:
(1).简洁,提升阅读效率
(2).阅读代码的人可以在不用查看函数体或文档,就立刻意识到哪些参数是可以被省略的。
(3).代码优化,即使未来的版本在对外接口中,彻底拿掉这个参数,也不会导致以前的代码无法运行
参数变量是默认声明的,所以不能用let或const再次声明,否则会报错。
function foo(x = 5) {
let x = 1; // error
const x = 2; // error
}
使用参数默认值需要注意的:
(1).函数不能有同名参数
(2).参数默认值不能够传值,每次都重新计算默认值表达式的值。也就是参数默认值是惰性求值的。
// 同名函数报错
function foo(x, x, y = 1) {
// ...
}
// SyntaxError: Duplicate parameter name not allowed in this context
******************************
let x = 99;
function foo(p = x + 1) {
console.log(p);
}
foo() // 100
x = 100;
foo() // 101
上面代码中,参数p
的默认值是x + 1
。这时,每次调用函数foo
,都会重新计算x + 1
,而不是默认p
等于 100。
(2)与解构赋值默认值结合使用
参数默认值可以与解构赋值的默认值,结合起来使用。
function foo({x, y = 5}) {
console.log(x, y);
}
foo({}) // undefined 5
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined
上面代码只使用了对象的解构赋值默认值,没有使用函数参数的默认值。只有当函数foo
的参数是一个对象时,变量x和y才会通过解构赋值生成。如果函数foo
调用时没提供参数,变量x
和y
就不会生成,从而报错。通过提供函数参数的默认值,就可以避免这种情况.
function foo({x, y = 5} = {}) {
console.log(x, y);
}
foo() // undefined 5
上面代码指定,如果没有提供参数,函数foo
的参数默认为一个空对象。
(3).参数默认值的位置
通常情况下,函数默认值应该是函数的尾参数,这样比较容易看出到底省略了哪些参数。如果非尾参数设置默认值,这个参数无法被忽略,否则会报错,除非显式输入`undefined`,传入`undefined`将会触发该参数的默认值,`null`没有这个效果
/ 例一
function f(x = 1, y) {
return [x, y];
}
f() // [1, undefined]
f(2) // [2, undefined])
f(, 1) // 报错
f(undefined, 1) // [1, 1]
// 例二
function f(x, y = 5, z) {
return [x, y, z];
}
f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 报错
f(1, undefined, 2) // [1, 5, 2]
function foo(x = 5, y = 6) {
console.log(x, y);
}
foo(undefined, null)
上面代码中,x
参数对应undefined
,结果触发了默认值,y
参数等于null
,就没有触发默认值。
(4)函数的 length 属性
指定了默认值后,函数length
将返回不包含默认值的参数个数,同样的rest参数也不会计入length
属性,指定了默认值后,length属性将失真。
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了。
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
(6).作用域
一旦设置了函数默认值,函数在声明初始化时,函数就会形成一个单独的作用域,初始化结束后这个作用域会消失。不设置函数默认值就不会出现作用域。
var x = 1;
function f(x, y = x) {
console.log(y);
}
f(2) // 2
上面代码中,参数y的默认值等于变量x
。调用函数f时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x
指向第一个参数x
,而不是全局变量x
,所以输出是2
。
如果此时,全局变量x不存在,就会报错。
function f(y = x) {
let x = 2;
console.log(y);
}
f() // ReferenceError: x is not defined
2.rest参数
ES6引入rest参数(形式为“...变量名”),用于获取函数的多余参数。
函数参数搭配的变量是一个数组,该变量将多余的参数翻到里面。
function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
add(2, 5, 3) // 10
上面代码的add
函数是一个求和函数,利用 rest
参数,可以向该函数传入任意数目的参数。
下面是一个 rest
参数代替arguments
变量的例子。
// arguments变量的写法
function sortNumbers() {
return Array.prototype.slice.call(arguments).sort();
}
// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();
上面代码的两种写法,比较后可以发现,rest
参数的写法更自然也更简洁
注意:
(1). rest参数之后不能有其他参数,即只能是最后一个参数,否则会报错
(2).函数的length属性不包括rest参数
// 报错
function f(a, ...b, c) {
// ...
}
(function(a) {}).length // 1
(function(...a) {}).length // 0
(function(a, ...b) {}).length // 1
3.箭头函数
基本用法
ES6 允许使用“箭头”(=>
)定义函数。
var f = v => v;
// 等同于
var f = function (v) {
return v;
};
如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。
var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
return num1 + num2;
};
网友评论