持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情
函数属于什么类型?——属于JavaScript的基本类型中的Object,函数是对象
函数的属性
name
函数的name属性很智能
- 普通的函数声明的name属性
function fun(){
console.log('this is a function')
}
console.log(fun.name) // fun
- 匿名函数赋值后的name属性,可以看到匿名函数在赋值后也有了name属性
let fun1 = function() {
console.log('this is fun1')
}
console.log(fun1.name) // fun1
- 默认值方式的赋值同样可以有类似的效果
function f(fun2=function(){
console.log('this is fun2')
}){
console.log(fun2.name) // fun2
}
以上例子可以看出,如果函数在声明的时候没有name,在赋值的时候会根据上下文推测一个name,也有时候引擎也无法根据上下文推测出name的情况,name会是空。
length
- 这是函数的内建属性,返回函数入参的个数,不包括rest参数
function test1(a){}
function test2(a,b){}
function test3(a,b,c){}
function test4(a,...rest){}
test1.length //1
test2.length //2
test3.length //3
test4.length //1
- 函数的length属性可以用于运行时检查,比如一些JavaScript的库函数根据用户传入的参数的类型/个数等来实现函数的多态
自定义属性
- 自定义属性不是函数内的局部变量,在函数存储属性,不会影响函数的执行 比如记录函数调用时的时间戳
function fun(){
console.log('this is fun')
fun.timeStamp = new Date().getTime()
}
fun() // this is fun
console.log(fun.timeStamp) //1656254521416
fun() // this is fun
console.log(fun.timeStamp) //1656254537343
- 自定义属性可以替换闭包中的变量,两者的不同在于闭包中的变量只有函数外部的词法环境可以修改,而如果是函数的属性,就可以很容易被的修改属性的值
命名函数表达式
let test = function t(arg){
console.log('this function's arguement is', arg)
}
在调用t的时候,依旧可以使用test()来调用,但是加入了t之后,可以在函数内部引用自己,并且在函数外不可见
let test = function t(arg){
if(arg){
console.log('this function's arguement is', arg)
} else {
t('default')
}
}
test() // this function's arguement is default
t() // error,undefined
当然,也可以这样写:
let test = function (arg){
if(arg){
console.log('this function's arguement is', arg)
} else {
test('default')
}
}
但是这样写容易有风险,因为test可能会被其他代码改变,如果test无意见被赋予了其他值(比如null)之后,这样写就出现了错误,这样的写法也不利于排查,所以使用命名函数表达式可以有效的避免这类问题