重学ES6 函数的扩展(上)

本文深入探讨了ES6中函数参数的默认值用法,对比了ES6前后实现方式的区别,并详细解析了参数默认值的惰性求值特性及与解构赋值的结合使用。同时,介绍了rest参数的使用方法,展示了如何利用rest参数简化函数参数处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数参数的默认值

基本用法

在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
复制代码

以上写法会有一个问题,就是当我们传进去一个y值,但是其对应的布尔值为false,例如 log('hello',''),结果被修改为了默认值! 所以,为了避免这个问题,我们替换如下语句

if(typeof y === 'undefined'){
    y = 'world'
}
复制代码

在ES6里面就简单多了,可以直接在参数设置默认值

function log(x, y = 'world') {
    console.log(x ,y)
}
log('hello') //hello world
log('hello', 'china') //hello china
log('hello','') // hello
复制代码

有一点需要注意 参数默认值不是传值的,而是每次重新计算默认值表达式的值,参数默认值是“惰性求值的”

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
复制代码

注意:参数变量是默认声明的,在函数体中,不能再用 let const 进行声明,也 不允许有同名参数。

结合解构

function foo({x, y = 5}){
    console.log(x, y)
}

foo({}) // undefined 5
foo({x:1}) // 1, 5
foo({x: 1, y: 3}) // 1, 3
foo() //报错
复制代码

只有函数的参数是一个对象时,变量x y 才会通过解构赋值生成。如果函数调用时,参数不是对象,变量x y 就不会生成,会报错。

在前面文章 重学ES6 解构我们他提到过函数参数的默认值,jQuery ajax的解构

这里再用一个新的API写一遍

function fetch(url,{body = '', metthod = 'GET', headers = {}}){
    console.log( method )
}

fetch('http://example.com', {}) // GET
fetch('http://example.com') // 报错
复制代码

这个写法不能省略第二个参数~那就太不好了。。。所以,我们要再结合函数的默认值,就可以省略第二个参数了

function fetch(url,{body = '', metthod = 'GET', headers = {}} = {}){
    console.log( method )
}

fetch('http://example.com', {}) // GET
fetch('http://example.com') // GET
复制代码

注意:在函数传参解构中,只要传入实际参数,那么就拿传入的实际参数进行解构,如果没有传入实际参数,且参数写了默认值,函数参数得到值是 undefined 时,被赋予默认值。

// demo 1
function m1 ({x = 0,y = 0} = {}){
    return [x, y]
}

// demo 2
function m2 ({x, y} = {x: 0, y: 0}){
    return [x, y]
}

//x y 都无值
m1({}) //[0, 0]
m2({}) // 没有写默认值,对实参进行解构,[undefined, undefined]

m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]
复制代码

默认参数位置

通常,定义了默认值的参数应该是函数的尾参数。这样可以看出到底省略了哪些参数。

function f(x, y, z = 1){
    return [x, y, z]
}

f() // [undefined, undefined, 1]
复制代码

函数的 length

指定了默认值以后,函数的 length 属性将返回没有指定默认值的参数个数。指定了默认值后,length属性将失真

(function (a) {}).length //1
(function (a = 5)).length // 0
(function (b ,c ,a = 5)).length // 2
复制代码

length 属性 含义是 “函数预期传入的参 数个数” ,某个参数指定默认值以后,函数传入参数个数就不包含这个了,rest参数也不会计入length属性

作用域

设置了参数的默认值后,函数进行初始化时,参数会形成一个单独的作用域。等到初始化结束,这个作用域就会消失。这种语法行为在不设置参数时是不会出现的。

var x= 1

function f(x,  y = x){  //相当于 let x 
    console.log(y)
}

f(2)
复制代码
// 如果此时全局 x 不存在,就报错了
function f(y = x){  //相当于 let y = x 
    console.log(y)
}

f()  // x is nit defined
复制代码
var x = 1

function f(x = x){  //相当于 let x = x  暂时性死区
    console.log(x)
}

f()  // x is nit defined
复制代码

如果参数是一个函数

let foo = 'ourter'

function bar (func = () => foo){ //在这里,函数里面的foo没有定义,所以foo指向外层的 foo
    let foo = 'inner'
    console.log(func())
}

bar()
复制代码

又一个例子

此例子,x共有3个,全局作用域下 foo函数参数作用域 还有 foo函数内部作用域,共三个,互不相同

var x =1

function foo(x, y = function() { x = 2}){
    var x = 3
    y()
    console.log(x)
}

foo() // 3
x // 1
复制代码

但是,如果去掉 foo 函数 内部的 var x = 3 的 var,那么就剩下两个不同的x,即:全局下的x 和 函数 foo 参数作用域下的x ,因为函数内部的 x 和 函数参数的x 已经是同一个x

var x =1

function foo(x, y = function() { x = 2}){
    x = 3
    y()
    console.log(x)
}

foo() // 2
x // 1
复制代码

两个例子都不会影响外部全局变量x的值。

应用

参数默认值,可以指定某一个参数不能省略,如果省略了,就跑出一个错误

function throwIfMissing(){
    throw new Error('Missing parameter')
}

function foo(mustBeProvided = throwIfMissing()){
    return mustBeProvided
}

foo()
复制代码

rest 参数

es6 引入了 rest参数,(形式为 ...变量名),用于获取函数的多余参数,也就不需要使用 arguments 参数对象了。 rest参数搭配的变量是一个数组,该变量将多余的参数放入其中。

function add(...values){
    let sum = 0
    for(var val of values){
        sum += val
    }
    return sum
}
add(1,2,3) // 6
复制代码

几个例子

之前,用arguments的写法

// Array.prototype.slice.call(arguments)  将参数转化为数组
// array.sort
function sortNumbers() {
    return Array.prototype.slice.call(arguments).sort()
}

// rest 参数的写法
//...numbers 将numbers 转化为数组
const sortNumbers = (...numbers) => numbers.sort()
复制代码

rest参数改写 push

function push(array,...items){
    items.forEach(function(item){
        array.push(item)
    })
}

var a = []

push(a,1,2,3)
复制代码

rest 参数之后,不能再有其他参数,所以,rest只能是最后一个参数。而且,函数的length,不包括rest参数。

转载于:https://juejin.im/post/5cb51788e51d456e4514f53a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值