3. 函数默认值 & 剩余参数 & 扩展运算符

580 阅读3分钟

带参数默认值的函数

当函数被调用,而缺少传入参数,结果就会返回一个Nan

function add(a, b) {
    return a + b;
}
console.log(add(30)); NaN

为了避免这种情况,可以给参数一个默认值,没有传入参数的时候采用默认值赋值,有部分传参的时候按左到右顺序给形参赋值

es5中的写法:

function add(a, b) {
    a = a || 10;
    b = b || 20;
    return a + b;
}
console.log(add()); //打印结果 30

es6中的写法:

function add(a = 10, b = 20) {
    return a + b;
}
console.log(add()); //打印结果 30
console.log(add(30)); //打印结果 50
console.log(add(30,60)); //打印结果 90

es6的写法还有两个好处:首先,可以立刻意识到 哪些参数是可以省略的,不用查看含糊整体或者文档。其次,有利于将来代码优化,即使未来的版本在对外接口中,彻底拿掉这个参数,也不会导致以前的代码无法运行

参数默认值也可以是一个函数

可以实现在没有参数传入的时候执行另一个函数

function add(a, b = fn(5)) {
    return a + b;
}
function fn(val) {
    return val + 10;
}
console.log(add(30,2));//打印结果 32
console.log(add(30));//打印结果 45

剩余参数

剩余运算符:把多个独立的参数合并到一个数组中 → 放在函数的传入形参

由三个点 ... 和一个紧跟着的具名参数指定 ...keys,剩余参数解决了最大的问题就是arguments问题

es5写法: arguments方法会打印出在0的整个对象,所以i必须从1开始遍历来跳过对book对象本身的遍历

let book = {
    title: 'es6教程',
    year: 2019,
    price: 58
}

function pick(obj) {
    let result = {};
    for (let i = 1; i < arguments.length; i++) {
        
        // console.log(arguments);
        //打印结果0: {title: "es6教程", year: 2019, price: 58} 1: "title" 2: "year"
        //会打印出在0的整个对象,所以i必须从1开始遍历来跳过对book对象的遍历
        result[arguments[i]] = obj[arguments[i]]
    }
    return result;
}

let bookData = pick(book, 'title', 'price');//传入不确定数量参数
console.log(bookData);//{title: "es6教程", price: 58}

es6剩余参数写法: 可以让传入的参数直接通过对剩余参数遍历,来获取对象内的属性

let book = {
    title: 'es6教程',
    year: 2019,
    price: 58
}

function pick(obj, ...keys) {
    let result = {};
    for (let i = 0; i < keys.length; i++) {
        result[keys[i]] = obj[keys[i]];
    }
    return result;
}

let bookData = pick(book, 'title', 'price');
console.log(bookData);//{title: "es6教程", price: 58}

扩展运算符

扩展运算符也是 ... 且只能放在最后一个参数,放在最前,放在中间,放两个都是错误的

把一个数组分割,并将各个项作为分离的参数传给函数 → 放到被调用的函数或者方法的()内

const arr = [10, 42, 34, 7, 1, 65, 3, 63, 32];
const [a, b, ...c] = arr;
console.log(c);//[34, 7, 1, 65, 3, 63, 32]

//es5处理数组中的最大值,使用apply来获取
//apply:方法能劫持前面的对象,继承后面的对象的属性 apply(obj,args)
console.log(Math.max.apply(null,arr)) //打印结果 65

//es6扩展运算符的使用更加方便
console.log(Math.max(...arr))//打印结果 65

...arr 会把数组拆分成一个个参数一起放到()内

把两个数组合并,而不是把两个数组放入新的数组中

let a = [1, 2, 3, 4, 5];
let b = [6, 7, 8, 9, 0];
let ab = [a, b];//把a和b放到ab数组中- 0:[1, 2, 3, 4, 5] 1:[6, 7, 8, 9, 0]
let ab = [...a, ...b];//吧a和b两个数组合并-[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
console.log(ab)

把一个对象分割

let obj = {
    id: 3,
    name: 'Max',
    age: 23
}
let { id, ...rest } = obj;
console.log(id); //3
console.log(rest); //{name: "Max", age: 23}

把两个对象合并

let obj1 = {
    id: 3,
    name: 'Max'
}
let obj2 = {
    age: 23,
    sex: 'man'
}
// var box = Objecte.assign({},obj1,obj2) 浅拷贝合并写法
let box = { ...obj1, ...obj2 };
console.log(box);//{id: 3, name: "Max", age: 23, sex: "man"}
//如果两个对象有相同属性,后面的对象的属性值会覆盖前面的属性值