首页 > 代码库 > ES6--函数的扩展
ES6--函数的扩展
1.函数的默认值
从ES6开始,允许为函数参数设置默认值,即直接写在参数定义的后面。这样做使代码变得简洁自然,另外还有两个好处:
- 可以方便明确的知道哪些参数有默认值是可以省略的
- 有利于将来的代码优化,即使去掉这个参数也不会导致以前的代码无法运行
另外,参数变量是默认声明的,因此不能再使用let和const命令再次声明。定义了默认值的参数应该是函数的尾参数,这样就可以很容易的看出到底省略了哪些参数。如果尾部参数没有设置默认值那么是无法省略的。另外也无法直接省略处在中间的有默认值的参数,除非显示传入undefined
与解构赋值结合使用
function m1({x:0,y:0} = {}){ return [x, y]; } function m2({x,y} = {x:0,y:0}){ return[x, y]; } m1()//[0,0] m2();//[0,0] m1({x:3, y:8});//[3,8] m2({x:3,y:8});//[3,8] m1({x:3});//[3,0] m2({x:3});//[3, undefined]
length属性
指定默认值以后函数的length属性返回的是没有指定默认值参数的个数,因为length属性的含义就是函数预期传入参数的个数,当某个参数指定了默认值以后预期的传入参数就不再包括已经指定默认值的参数。
2.rest参数与扩展运算符
ES6引入rest参数(形式为’…变量名’),用于获取函数的多余参数,该功能类似于Java中的不确定数量的参数,rest参数将不定个数的参数转换为名称为指定变量名的数组,然后我们可以通过众多的数组函数对其进行操作
注意一点,rest函数必须是函数的最后一个参数否则会报错
与rest参数相反,扩展运算符 … 将一个数组转为用逗号分隔的参数序列。扩展运算符提供了众多的用途
替代数组的apply方法
//ES5 Math.max.apply(null,[14,2,4]); //ES6 Math.max(...[14,2,4]);
合并数组
var arr1 = [‘a‘, ‘b‘]; var arr2 = [‘c‘, ‘d‘]; var arr3 = [‘e‘]; //ES5 arr1.contact(arr2,arr3); //ES6 [...arr1, ...arr2, ...arr3];//[‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘]
与解构赋值结合
两者可以结合使用生成数组
const [first, ...rest] = [1, 2, 3, 4, 5]; first //1 rest //[2,3,4,5]
将字符串转为数组
[..."hello"]// [‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘0‘]
转换类似数组的对象、Set、Map以及Generator函数、
//转换对象 var nodelist = document.querySelectorAll(‘div‘); var array = [...nodelist] //转换Map。Map和Set都是具有Iterator的对象, 只要是具有Iterator接口的对象都可以使用扩展运算符 let map = new Map([ [1, ‘one‘], [2, ‘two‘], [3, ‘three‘], ]); let arr = [...map.keys()];//[1, 2, 3] //转换Generator函数,Generator函数运行后返回一个遍历器对象,因此也可以使用扩展运算符 var go = function*(){ yield 1; yield 2; yield 3; };
3.name属性
函数的name属性返回函数名,如果是匿名函数,ES5返回空字符串,而ES6返回实际的函数名。Function构造函数返回的函数示例name属性值为’anonymous’,bind返回的函数name属性值会加上’bound’前缀
var func1 = function(){}; func1.name;//ES5:"" ES6:func1 //如果将一个具名函数返回给一个变量,ES5/ES6都会返回这个具名函数原本的名字而不是变量名 const bar = function baz(){}; bar.name();//baz
4.箭头函数
ES6允许使用* 箭头 => *定义函数,箭头左边为参数,右边为方法体。如果不需要参数则用圆括号代表参数部分,如果方法体多于一行则用大括号括起来并用return表示返回。
var f = v => v; //等价于 var f = function(v){ return v}; var f = ()=>5; //等价于 var f = function(){ return 5; }
箭头函数的几点注意:
* 函数体内的this总是该函数定义时所在的对象。因为箭头函数根本没有自己的this,因此其内部的this就是外层代码块的this
* 不可以当做构造函数,即不可以使用new命令
* 不可以使用arguments对象,该对象在函数体内不存在, 可以用rest代替
* 不可以使用yield命令,因此箭头函数无法用作Generator函数
5.函数绑定、尾逗号以及尾调用优化
ES7提出了函数绑定用来取代call、apply、bind调用,运算符是双冒号* :: *, 其坐标是一个对象,右边是一个函数,它将自动将左边的对象作为上下文环境(即this对象)绑定到右边的函数中。其返回的还是原对象因此可以使用链式调用
尾调用优化
尾调用是函数式编程的一个重要概念, 指某个函数的最后一步是调用另一个函数。尾调用可以不出现在尾部,只要是函数操作的最后一步即可。
在函数的调用过程中,会形成调用栈,尾调用与其他的调用不同在于因为尾调用是函数的最后一步操作,因此不需要外层函数的调用栈,这样就只保留了内层的调用栈。因此如果所有的函数都是尾调用那么完全可以做到每次执行调用时只有一帧,将大大的节省内存,这就是所谓的尾调用优化
尾调用可以对递归进行优化。函数调用自身成为递归,如果尾调用自身就成为尾递归。因为可能需要保存大量的调用栈因此非常消耗内存。尾递归很好的解决了这一问题。
尾递归的实现往往需要改写递归函数,确保其最后只调用自身。方法就是:把所有用到的内部变量变为函数的参数。但这么做会导致函数的可读性降低,这里有两个方法解决:
一是在尾递归函数之外再提供一个正常形式的函数来调用尾递归函数,另一个就是柯里化,是函数式编程的一个概念,是将多参数的函数转换为单参数的形式。
尾逗号
从ES6开始允许函数的最后一个参数有尾逗号
function func( foo, bar,){ }
ES6--函数的扩展