参数默认值: 如果没有传参数就相当于传的是 undefined, 不能是 null, 因为会被解构为 0
function sum(a, b = 2, c = 3) {
return a + b + c;
}
sum(11); // 16 , 这就相当于sum(11, undefined, undefiend), 但是必须是undefined,他才给你解析为默认值, 不然传null的话 (sum(11, null, null) = 11),它会给你解析为0
面试题
function test() {
console.log("abc");
return document.getElementsByClassName("container")[0];
}
function createEle(ele = "div", container = test(), content = "何难勋最帅") {
const el = document.createElement(ele);
if (content) {
el.innerText = content;
}
container.appendChild(el);
}
// 打印两次, 因为前面两次都传的是undefined, 所以使用默认值,执行test(),第三次传了值,就用传入的值,不执行test
createEle(undefined, undefined, undefined);
createEle(undefined, undefined, "何难勋");
createEle(undefined, document.querySelector(".wrapper"));
扩展
- 参数对于在严格模式下不一样,传参进来,如果在非严格模式下,你在函数里面修改了值,它的 arguments 里面的值也会变,但是在严格模式下,他们两个是脱离的,你定义的值,arguments 里面的值不会变
注意点: 如果设置了默认值,该函数会自动变为在严格模式下执行,arguments 和形参脱离, 所以尽量不要使用 arguments,因为可能会造成一些问题
function test (a, b) {
console.log(arguments[0], arguments[1]) // 1, 2
a = 3
console.log(arguments[0], arguments[1]) // 3, 2
console.log(a, b) // 3,2
}
test(1,2)
'use strict' ------------严格模式下
function test (a, b) {
console.log(arguments[0], arguments[1]) // 1, 2
a = 3
console.log(arguments[0], arguments[1]) // 1 , 2 : 在严格模式下,arguments的值不变
console.log(a, b) // 3,2
}
test(1,2)
- 留意暂时性死区
- 形参和 ES6 中的 let 和 const 声明一样,具有作用域,并且根据参数的声明顺序存在暂时性死区
function test(a, b = a) {
console.log(a, b);
}
test(1, 2); // 1, 2 ; 因为都传入了值,所以不会使用默认值
test(1); // 1, 1 ; 因为a已经被定义为1了,所以执行到b的时候,能拿到a的值
function test(a = b, b) {
console.log(a, b);
}
test(1, 2); // 1, 2 ; 因为都传入了值,所以不会使用默认值
test(1); // 报错,会说b还没初始化就被调用
注意: let 在函数内部定义变量,不能和形参同名,否则会报错
剩余函数: ES6 的剩余参数专门用于收集末尾的所有参数,将其放置到一个形参数组中;
解决的问题:
剩余参数:
解决问题:
- arguments:
1. 如果和形参配合使用,容易导致混乱,eg:在形参没有设置默认值的情况下,在函数里面修改了形参的值之后,arguments里面的值也会变; 但是设置了默认值之后,函数就自动变为了'严格模式',形参和实参就会相互脱离,你修改值不会改变arguments的值
2. 从语义上,使用arguments获取参数,由于形参缺失,无法从函数定义上理解函数的真实意图
- 就是写的函数让调用者爽,不用给它规定传什么类型,如一般我们的方法会要求传数组...
用来代替arguments,不仅让调用者不用关注是什么类型,任意传值,然后就是arguments的缺陷,
// 收集参数: 一定是收集最后的参数的
function test(...args) {
// args收集了所有的参数,形成了一个数组
}
*细节
// 数组克隆
var arr = [...arr1]
// 对象浅克隆,没有进行深层次的克隆,也就是第二层对象就相同了
var obj = {...obj1}
// 对象浅克隆,没有进行深层次的克隆,也就是第二层对象就相同了
// eg:
var obj = { name: 'hnx', obj1: { age: 18}}
var obj2 = {...obj, name: 'xtf' }
obj1.obj1 == obj.obj1 // true , 原因是它只是展开了第一层次,而没有展开第二层
*展开: ...
function test(a, b, c) {
console.log(a, b, c)
}
var arr = ['adf', 'af', 'affgd']
test(...arr) // 将arr展开传入
*柯里化
function cal(a, b, c, d) {
return a + b * c - d
}
// cal(1,2, 3, 4)
// cal(1,2, 4, 5)
// cal(1,2, 6, 7)
// cal(1,2, 8, 9)
// 调用的时候前两个参数都是一样,那就用一个curry方法,将固定的参数拿出去,返回一个新的函数执行剩余的参数
const newCal = curry(cal, 1, 2)
console.log(newCal(3, 4)) //1 + 2 * 3 - 4
console.log(newCal(4, 5)) //1 + 2 * 4 - 5
console.log(newCal(6, 7)) //1 + 2 * 6 - 7
console.log(newCal(8, 9)) //1 + 2 * 8 - 9
const newCal2 = newCal(3)
console.log(newCal2(9)) // 1 + 2 * 3 - 9 参数不够,那继续返回一个函数再次执行,直到参数传完,才结束
// curry: 柯里化,用户固定某个函数的前面的参数,得到一个新的函数,新的函数调用时,接受剩余的参数
function curry(fn, ...args) {
// console.log(args) // 是一个数组
return function (...subArgs) {
// 判断参数是否传完,就将两个数组加起来的长度看是否大于fn形参的长度
// 拼接的方法
// 1. const allArgs = [...args, ...subArgs]
const allArgs = args.concat(subArgs);
if (allArgs.length >= fn.length) {
// 参数够了
return fn(...allArgs)
} else {
// 参数不够
return curry(fn, ...allArgs)
}
}
}
网友评论