ES6中我们来看下函数有哪一些改变:
一、函数的默认值:
在ES5中设置默认值是在函数体内:
如果没传递参数
function test(num,callback){
var num = num || 10;//不传递参数默认是10
var callback = callback || function (param){console.log(param*10)};
callback(num)
}
test()//100
而在ES6中默认值的写法是写在形参中:(默认值参数可以是:字符串、数字、数组、或者对象、或函数都可以。)
函数内部代码更简洁了
function test(num=10,callback=function (param){console.log(param*10)}){
callback(num)
}
test()//100
补充:
参数一使用默认值,参数二不需要,实参第一个参数可以传undefined。
function test(a = 1,b = 2){
return a + b
}
let result = test(undefined,10)
console.log(result) //11
下边我们来看下ES6的默认值写法对类数组对象-------arguments(也叫实参列表)是否有影响:
// es5
function test(a,b) {
console.log(arguments);//Arguments(2) [2, 3, callee: (...), Symbol(Symbol.iterator): ƒ]
console.log(arguments.length);//2
}
test(2,3)
// es6
function test(a = 4,b = 5) {
console.log(arguments);//Arguments(2) [2, 3, callee: (...), Symbol(Symbol.iterator): ƒ]
console.log(arguments.length);//2
}
test(2,3)
下边是截图:
结论:默认值对arguments无影响;
二、默认值的暂时性死区:
跟let和const一样默认参数也是有暂时性死区:
当a初始化的时候,b还未定义,(也就是说当a想用b的值得时候,b还未定义)所以第一个参数对于b来说是暂时性死区
function test( a = b, b ){
console.log(a+b);
}
test( undefined, 2 )//Uncaught ReferenceError: b is not defined
三、不定参数的使用
所谓的不定参数就是参数不确定是多少个,一般形参会使用展开(或扩展)运算符来表示。
下边例子中形参 ...arr 起到收集参数的作用,它会把实参全部收集起来,统一的放到一个数组中去!关于展开运算符(或扩展运算符)我们在下一章节来详细聊下 !
eg:
//例一
function test1(...arr){
console.log(arr);
}
test1({name:"lxc",age:20})//[{name:"lxc",age:20}]
//例二
function test2(...arr){
console.log(arr);
}
test2(1,2,3)//[1,2,3]
//例三:...arr必须放在所有参数的最后
function test3(a,b,...arr){
console.log(a,b,arr);
}
test3(1,2,3,4)//1 2 [3,4]
四、箭头函数 ( )=>{ }
直接举例:
let a = [1,2,3];
a.forEach((ele,index)=>{
console.log(ele)
})
参数只有一个的时候,可省略括号:
let a = [1,2,3];
a.forEach(ele=>{
console.log(ele)
})
参数只有一个且函数内部return有返回值的时候,可简写成一行省略return:
( num-----函数名;第一个n------函数参数;第二个n----要返回的数据)
let num = n=>n
console.log(num(2))//2
function a(b) {
return function(c){
return b + c;
}
}
// 等于
var a = b=>c=>b+c;//两个箭头以上的也叫做高阶函数
console.log(a(1)(2)) //3
如果返回是一个对象:后边需加括号,也就是返回一个表达式
let a = (b,c)=>({name:b,age:c})
console.log(a("lxc",20))//{name:"lxc",age:20}
关于箭头函数和普通函数的区别:
1、箭头函数中没有this,函数内部的this指向父级且非箭头函数,而且不能改变this指向;
2、箭头函数没有super;
3、箭头函数没有arguments(这里要说明下,箭头函数里边的arguments指向外层非箭头函数的arguments);
4、不能使用new;
5、没有原型;
6、不支持重复命名参数。
来一个arguments的例子:
function a(){
return ()=>{
return arguments
}
}
console.log(a(1,2)())//Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
上边代码,里边返回了一个arguments正是外层父级的aruguments。。。。
五、尾调用的优化
尾调用是指在函数return的时候调用一个新的函数,由于尾调用的实现需要存储到内存中,在一个循环体中,如果存在函数的尾调用,你的内存可能爆满或溢出。
而在ES6中,引擎会帮你做好尾调用的优化工作,你不需要自己优化,但需要满足下边3个要求:
1、函数不是闭包;
2、尾调用是函数最后一条语句;
3、尾调用结果作为函数返回。
eg:满足尾调用的例子:
"use strict";
function b(){};
function a(){
return b()
}
下边都是不满足的写法:
//没有return-----不优化
"use strict";
function b(){};
function a(){
b()
}
//不是直接返回函数-----不优化
"use strict";
function b(){};
function a(){
return 1 + b()
}
//尾调用是函数不是最后一条语句---不优化
"use strict";
function b(){};
function a(){
let c = b()
return c
}
//闭包-----不优化
"use strict";
function a(){
const num = 2;
return function b(){
consoel.log(num)
}
}
在平时开发中,尾调用的实际用途----递归函数的优化:
"use strict";
function a( n, p=1 ){
//递归出口
if( n <=1 ){
return 1* p
}
let s = n * p;
return a( n-1, s )
}
// 求3的阶乘(1*2*3)
let sum = a(3)
console.log(sum)//6