每天十分钟学好ES6--function函数的扩展

Posted 桃子叔叔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每天十分钟学好ES6--function函数的扩展相关的知识,希望对你有一定的参考价值。

es6中函数的扩展需要掌握的重点有:

  • 函数参数与解构赋值默认值结合使用
  • rest参数
  • 箭头函数=>
  • 尾调用优化

一、函数参数的默认值

首先看一下函数参数默认值的一段代码:

function foo ({x, y = 5}) {
	console.log(x, y)
}
foo({}) // undefined 5
foo({x:1}) // 1 5
foo({x: 1, y: 2}) // 1 2
1.1 es6函数默认值的写法有几个好处
  • 比es5简洁
  • 阅读代码的人可以立刻意识到哪些参数可以省略,而不需要查看文档
  • 有利于未来代码优化,即使彻底拿掉这个参数也不会导致代码无法运行
1.2 默认值–设置默认值的参数需要是尾参数

否则参数无法省略,比如以下代码会报错

function foo ({x=1, y}) {
	console.log(x, y)
}
foo({, 1}) // 报错原因逗号是Unexpected token

其实说白了,设置参数的默认值就是为了可以省略参数,如果不是尾巴参数设置默认值,无法只省略该参数而不省略其后的参数。

1.3 默认参数作用域问题

设置参数默认值,函数进行声明初始化后,参数形成单独的作用域

let x = 1
function f(y= x) {
	let x = 2
	console.log(y)
}
f()//1 --函数体内的局部变量影响不到默认值变量x

从上面可以看出来,函数参数的默认值在初始化时就形成了单独的作用域,函数体内的let x = 2作用域不会影响到它

1.4 参数默认值的运行时机

参数的默认值不是在定义是执行,而是在运行时执行。如果参数已经赋值,默认值中的函数就不会执行。

二、rest参数

function add (...values) {
	let sum = 0
	for (let val of values) {
		sum += val
	}
	return sum
}
add(1, 2, 3, 4)

rest参数可以将多余的参数,组合成一个数组,这样不需要担心固定参数的限制,但要注意一点:

rest参数之后不能有其他的参数,不然会报错

三、箭头函数

箭头函数好用且语法简单,首先看一下:

var f = v => v

但是有几点要注意:

  • 函数体内的this对象是定义时所在的对象,而不是使用时所在的对象
  • 函数体内没有arguments,使用rest函数代替
  • 箭头函数不能用作Generator函数,不可使用yield命令

四、绑定this

  • 函数绑定运算符是双冒号(::),即对象::函数,将左边的对象作为上下文环境(即this对象)
  • 绑定在右边的函数上
let obj = {}
obj::add // add.bind(obj)
obj::add(...arguments) // add.apply(obj, arguments)

通过上面的代码可以很直观的看出来,其实呢,::双冒号语法就是用来取代call、apply、bind调用。

这个语法是es7的提案,但是现在已经支持了。

五、尾调用优化

尾调用优化很重要,这整个章节的重点,使用尾调用优化不仅可以避免发生栈溢出,还能节省内存,更是程序员需要掌握的基本素养。

function f(x){
	g(x)
}

像上面这样,在函数最后一步调用另一个函数,就是尾调用。

尾调用有一个问题,容易出现栈溢出

原因很简单,当f调用g时,会在f的调用帧上形成一个g的调用帧,如果g再进行尾调用,就会继续形成新的调用帧,以此类推,所有的调用帧形成一个调用栈–call stack

function Fibonacci(n){
	if (n <= 1) {
		return 1
	}
	return Fibonacci(n-1) * Fibonacci(n-2)
}
Fibonacci(10) //89
Fibonacci(100) // 堆栈溢出
Fibonacci(1000) // 堆栈溢出

就像上面的Fibonacci数列,非尾递归的情况下就会出现堆栈溢出,我们可以进行尾递归改写:

function Fibonacci2 (n, ac1=1, ac2=1) {
	if (n < 1) {
		return ac2
	}
	return Fibonacci2 (n-1, ac2, ac1 + ac2)
}

所谓的尾递归改写就是在函数最后一步调用自己,这样就不会形成新的调用帧,就很好的解决堆栈溢出的问题了~~

因此可以看出来尾调用优化对于递归操作意义重大

以上是关于每天十分钟学好ES6--function函数的扩展的主要内容,如果未能解决你的问题,请参考以下文章

每天十分钟学好ES6--function函数的扩展

每天十分钟学好ES6--function函数的扩展

每天十分钟学好ES6--数组

每天十分钟学好ES6--数组

每天十分钟学好ES6--数组

每天十分钟学好ES6--数组