函数参数默认值
(1) es5中模拟参数默认值:
function fn(name, count){
name = name || 'xiao ming'
count= count|| 1
console.log(name, count)
}
这样可以为没有传入的参数,设置为默认值。这种方式的问题:如果count传入0,即使这个值是合法的,但也会被设置为默认值1。
改进后:
function fn(name, count){
name = typeof name !== 'undefined' ? name : 'xiao ming'
count = typeof count !== 'undefined' ? count : 1
console.log(name, count)
}
(2) es6的做法:
function fn(name = 'xiao ming', count = 1){
console.log(name, count)
}
// name使用默认值
fn(undefined, 18)
扫盲: null是一个有效参数,传入null并不会使用默认参数
(3) 命名参数与arguments
的关系
es5非严格模式下,修改命名参数,会同步更新到arguments对象中;
而在es6或者严格模式中,命名参数和arguments是分离的
function fn1(name, count) {
name = 'li si'
count = 5
console.log(arguments[0])
console.log(arguments[1])
}
fn1('xiao wang', 4)
// 非严格模式下
// li si
// 5
// 严格模式下或es6环境中
// xiao wang
// 4
(4) 函数默认表达式
function count(){return 6}
function fn1(name, count = count()) {
console.log(name)
console.log(count)
}
fn1('xiao wang')
// 'xiao wang'
// 5
扫盲:
1. 参数、参数默认值、参数默认表达式都在同一个独立的作用域内;
2. 参数作用域中存在临时性死区,即后面的参数可以引用到前面的参数,反之不可以;
3. 参数作用域引用不到函数体内的变量
证明独立作用域的例子:
function fn(a, cb = () => { a.b = 1; console.log(a) }) {
var a = { a: 1 }
cb()
console.log(a)
}
fn({ c: 3 })
// { c: 3, b: 1 }
// { a: 1 }
cb
执行时,获取到的对象a
并不是函数体内新定义的,而是传入的参数a
,所以他们是在同一独立作用域的
无名参数
(1) es5中使用arguments获取不定数量的参数
// 如果没有注释,很难发现函数需要传入无命名参数
function fn(arr){
// i 从 1开始,需要跳过 arr这个命名参数
for(let i = 1, len = arguments.length; i < len; i++){
arr.push(arguments[i])
}
return arr;
}
console.log(fn([3],4,5,6,7)) // [3,4,5,6,7]
存在的问题:
- 并不容易发现函数,需要传入不定量参数;
- 如果有命名参数,arguments中既包含命名参数也包含无名参数,还需要拆分获取
(2) es6中,在参数前加三个点...
,表明这是一个不定参数,这个参数为数组,包含着自它以后传入的参数。
并且解决了上述es5
中的问题
function fn(arr, ...items){
for(let i = 0, len = items.length; i < len; i++){
arr.push(items[i])
}
return arr;
}
console.log(fn([3],4,5,6,7)) // [3,4,5,6,7]
不定参数的限制:
- 每个函数只能定义一个不定参数,而且只能处于所有参数末尾。错误示范:
function fn(a, ...b, c){}
- 对象的
setter
函数不能使用不定参数。错误示范:let obj = {set name(...value){}}
扫盲:
- 无论是否使用不定参数,
arguments
总是包括所有传入的参数- 函数的
length
属性,表示命名参数的数量,跟不定参数无关
函数的name
属性
-
function fn(){}
name为fn
-
let fn = function (){}
name为fn
-
let fn = function fn1(){}
name为fn1
,因为函数名比被赋值的变量权重高 -
let obj = {get firstName(){}, sayName(){}}
。obj.firstName
为getter函数,所以name为get firstName
;obj.sayName
name为sayName
- 通过
bind()
创建的函数,name会带有bound
前缀。fn.bind()
name为bound fn
- 通过
Function()
创建的函数,name为anonymous
。new Function()
name为anonymous
扫盲:函数name属性不一定能获取对函数的引用,它只是协助调试用的额外信息
网友评论