函数
函数参数的默认值
基本用法
ES6允许为函数的参数设置默认值,即直接写在参数定义的后面。
function log(x,y='World'){
console.log(x,y) //赋值什么的与解构赋值的一样
}
复制代码
函数的length属性
指定了默认以后,函数的length属性将返回没有指定默认值得参数个数。如果设置了默认参数length返回的就是0
作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域。等到初始化结束,这个作用域就会消失
rest
ES6引入了rest参数(形式为”...变量名“),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配 的变量是一个数组,该变量将多余的参数放入其中。
function add(...values){
let sum = 0
for (var val of values){
sum += val
}
return sum
}
add(2,3,5) // 10
复制代码
rest 参数之后不能再有其它参数(即只能是最后一个参数),否则会报错
严格模式
ES6规定只要函数参数使用了默认值、解构赋值或者扩展运算符,那么函数内部就不能显示设定为严格模式,否则就会报错。
function doSomething(a,b=a){
'use strict' //使用严格模式
}// 会报错
复制代码
解决这个的两种办法时我们可以使用以下方式:
- 第一种是设定全局性的严格模式
'use strict'
function doSomething(a,b=a){
//code
}
复制代码
- 第二种是把函数包在一个无参数的立即执行函数里面
const doSomething = (function(){
'use strict'
return function(value = 42) {
return value
}
})
复制代码
name属性
函数的name属性返回改函数的函数名
function foo(){}
foo.name // 'foo'
var f = function(){}
// ES5
f.name // ''
//ES6
f.name //'f'
复制代码
如果将一个具名函数赋值给了一个变量,ES5和ES6的name属性都返回这个具名函数原本的名字
剪头函数
基本用法
ES6允许使用‘剪头’(=>)定义函数
var f = v => v
// 完整写法
var f = function(v){
return v
}
复制代码
如果剪头函数不需要参数活需要多个参数,就使用圆括号代表参数部分。
var f = () => 5
复制代码
注意事项
剪头函数有以下几个使用注意事项
- 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象。
- 不可以当做构造函数。也就是说,不能使用new命令,否则会抛出错误。
- 不可以使用arguments对象,该对象在函数体内不存在。如果需要用,可以用rest参数代替。
- 不可以使用yield命令,因此箭头函数不能用做Generator函数。
箭头函数嵌套
es5
function insert(value) {
return {into:function (array) {
return {after:function (afterValue) {
array.splice(array.indexOf(afterValue) + 1, 0, value );// splice(要替换的位置,0为添加其它为删除的位数,要替换的值)
return array ;
}} ;
}} ;
}
insert(2) . into([l , 3)) . after(l) ; //[1 , 2, 3)
复制代码
箭头函数
let insert = (value) =>
({into: (array) =>
({after: (afterValue) => {
array.splice(array.indexOf(afterValue) + 1, 0, value)
return array
}
})
})
insert(2) . into([l , 3)) . after(l) ; //[1 , 2, 3)
复制代码
绑定this
箭头函数可以绑定this对象,大大减少了显式绑定this对象的写法(call、apply、bind), (针对箭头函数不适用于所有的场合,所以ES7提出了"函数绑定"运算符,**暂时还是一个提案,但是Babel转码器已经支持) 函数绑定运算符是并排的双冒号(::),双冒号左边的是对象右边的是函数。该运算符会自动将左边的对象作为上下文环境(及this对象)绑定到右边的函数上
foo::bar //等同于 bar.bind(foo)
复制代码
(后期补充知识点)
尾调用优化
什么事尾调用
尾调用(Tail Call)是函数式变成的一个重要概念,本身非常简单,就是指某个函数的最后一步是调用另一个函数。
function f(){
return g(x)
}
复制代码
尾调用之所以与其他调用不同,就在于其特殊的调用位置。
尾递归
函数调用自身称为递归。如果尾调用自身就称为尾递归。(递归非常耗费内存,因为需要同时保存成败上千个调用帧,很容易发生“栈溢出”错误(stackoverflow) 对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。
function factorial(n){
if(n === 1) return 1
return n*factorial(n-1)
}
factorial(5) //120
factorial(6) //720
复制代码
递归函数的改写
尾递归的实现往往需要改写递归函数,确保最后一步只调用自身。做到这一点的方法,就是把所有用到的内部变量改写成函数的参数。
严格模式
ES6的尾调用优化旨在严格模式下开启,正常模式下是无效的。
尾递归优化
尾递归只在严格模式下生效,那么在正常模式下,或者在那些不支持该功能的环境中我们需要:自己实现尾递归优化。 尾递归之所以需要优化,原因是调用栈太多造成溢出,只要减少调用栈就不会溢出。我们可以采用“循环”替换“递归”。
function sum(x,y){
if(y>0){
return sum(x +1,y-1)
}else {
retun x
}
} // 这个数太大会溢出
复制代码