JavaScript 的函数参数竟然能相互访问到?
·2 分钟·591 字·请注意时效性
是的,别骂了,我很菜,我在大惊小怪 😩。
#基础用法:前面的参数可以被后面访问
最简单的情况,后面的默认参数可以访问前面的参数:
const buildFn = (
name = 'Viki',
sayHi = () => {
console.log(name)
},
) => {
return sayHi
}
buildFn()() // 输出 Viki
buildFn('hi')() // 输出 hi
这个比较符合直觉,前面定义的 name 可以在后面的 sayHi 中使用。
#对象参数的访问
即使是对象类型的参数,也可以在后续参数中访问和修改:
const buildFn2 = (
obj = { name: 'Viki' },
sayHi = () => {
console.log(obj.name)
obj = { name: 'VIKI' }
},
sayHi2 = () => {
console.log(obj.name)
},
) => {
return { sayHi, sayHi2 }
}
buildFn2().sayHi() // 输出 Viki
buildFn2({ name: 'hi' }).sayHi2() // 输出 hi
这里 obj 参数可以在后面的 sayHi 和 sayHi2 中被访问到。
#重点来了:后面的参数也能被前面访问
这个就很有意思了,即使 name 定义在 sayHi 后面,sayHi 依然能访问到它:
const buildFn3 = (
sayHi = () => {
console.log(name)
},
name = 'Viki',
) => {
return sayHi
}
buildFn3()() // 输出 Viki,即使 name 在 sayHi 后面定义!
buildFn3(() => console.log(name), 'hi')() // 注意:外部传入的函数访问不到 name
注意:只有使用默认参数的函数才能访问到其他参数,外部传入的函数无法访问参数作用域。
#参数顺序不影响闭包捕获
再看一个更复杂的例子,参数重新赋值不会影响已经捕获它的其他参数:
const buildFn4 = (
sayHi = () => {
console.log(obj.name)
obj = { name: 'VIKI' } // 重新赋值 obj
},
sayHi2 = () => {
console.log(obj.name)
},
obj = { name: 'Viki' }, // obj 定义在最后
) => {
return { sayHi, sayHi2 }
}
buildFn4().sayHi() // 输出 Viki
buildFn4().sayHi2() // 输出 Viki(不受 sayHi 中重新赋值的影响)
每个默认参数函数都独立捕获了 obj 的引用,在 sayHi 中重新赋值 obj 不会影响 sayHi2 中的 obj。
#总结
JavaScript 函数的默认参数有个有意思的特性:
- 参数可以相互访问:无论是前面的参数还是后面的参数
- 不受顺序影响:后面定义的参数也能被前面的默认参数函数访问到
- 独立的闭包:每个默认参数函数都独立捕获参数引用
- 外部函数无法访问:只有默认参数函数能访问参数作用域,外部传入的函数不行
可以在控制台自己跑跑看,加深印象 🙃。
—— 本文完 ——