1、基本用法–指定默认值
es6,函数参数可以指定默认值
<script>
function fn(x,y=5){
console.log(x)
console.log(y)
}
fn(10,50)//10 50
fn(19)//19 5
fn(50,'')//50
</script>
2、与解构赋值默认值结合使用
参数默认值可以与解构赋值的默认值结合起来使用
当只有函数fn的参数是一个对象时,变量x和y才会通过解构赋值而生成,如果fn函数调用时参数不是对象,变量x,y就不会生成,只有参数对象没有y属性时,y的默认值5才会生效
<script>
function fn(x,y=5){
console.log(x)
console.log(y)
}
fn({ })//undined, 5
fn({x:1})//1 5
fn({x:1,y:2})//1 2,生效的是参数解构默认值
</script>
2、参数默认值的位置
通常情况下,定义了默认值的参数应该是函数的尾参数。因为这样比较容易看出到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是无法省略的。
3、函数的length属性
指定了默认值后,函数的length属性将返回实际参数个数-默认值个数的参数个数。也就是,指定了默认值后,相应的length占位失效
<script>
console.log((function (a) { }).length)//1
console.log((function (a=5) { }).length)//0
console.log((function (a,b,c=5) { }).length)//2 实际是3-1
</script>
4、作用域
一旦设置了参数的默认值,函数记性声明初始化是,参数会形成一个单独的作用域(context),初始化结束后,这个作用域就会消失。但如果不设置参数默认值时,是不会有这种情形的。
5、rest参数数组,类似于arguments对象
es6引入了rest参数(…变量名),用于获取函数的多余参数,这样就不需要再使用arguments对象,rest参数搭配的变量是一个数组,该变量将多余的参数放入其中。
<script>
function fn (...values){
let sum=0
for (let value of values){
sum+=value
}
return sum
}
let result=fn(1,2,3,4,5)
console.log(result)
</script>
6、name属性
name属性返回该函数的函数名,如果将具名函数赋值给一个变量,则返回原始名字
<script>
let myfun=function () {
}
console.log(myfun.name)//myfun
let myfun2=function hello () {
}
console.log(myfun2.name)//hello
</script>
7、箭头函数
- 由于箭头函数的大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对外面加上括号
var getTempItem=id=>({id:id,name:'temp'})
console.log(getTempItem())
</script>
- 箭头函数可以与变量解构结合使用
<script>
const full=({first,last})=>first+' '+last
console.log(full({first:'hello',last:'world'}))//hello world
</script>
8、箭头函数注意事项
- 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当作构造函数,也就是说,不可以使用new命令
- 不可以使用arguments对象,该对象在函数体内不存在,如果要用建议使用rets参数替代
- 不可以使用yield命令,因此,箭头函数不能用作Generator函数
下例:
函数隔1秒才执行,此时this应指向全局window对象,即id值为21.
但由于箭头函数的this总是指向函数定义生效时所在的对象即id值为32
<script>
function foo(){
setTimeout(()=>{
console.log("id:",this.id)
},1000)
}
let id=21
foo.call({ id:32 })//32
</script>
9、尾调用优化-概念
尾调用优化,某个函数的最后一步是调用另一个函数。
<script>
function foo(){
return goo()//尾调用
}
</script>
10、尾递归
尾递归要形成成百上千个调用帧,容易发生调用栈的栈溢出错误,但对于尾递归来说,由于只存在一个调用帧,所以永远不会翻身栈溢出错误