函数的拓展
参数的默认值
  在ES6之前,函数传入的参数没有默认值这一说法,所以我们经常要进行一些参数校验 
 function log(x, y) { if (typeof y === 'undefined') { y = 'world' } console.log(x, y) } log('hello')// hello world log('hello', '') // hello log('hello', 'abc')//hello abc复制代码
  ES6允许为函数的参数设置默认值,即直接写在参数定义的后面。 
 function log(x, y = 'world') { console.log(x, y) } log('hello') //hello world log('hello', '')//hello log('hello', 'abc')//hello abc复制代码
与解构赋值默认值结合使用
  参数默认值可以与解构赋值的默认值,结合起来使用。 
 function foo({ x, y = 5}) { console.log(x, y) } foo({x:1,y:2}) //1,2 foo({})// undefined 5 foo()// TypeError: Cannot destructure property `x` of 'undefined' or 'null'.复制代码
函数的length属性
  指定了默认值以后,函数的length属性,将返回没有指定默认值的参数个数。也就是说,指定了默认值后,length属性将失真。 
 (function (a) {}).length // 1 (function (a = 5) {}).length // 0 (function (a, b, c = 5) {}).length // 2 复制代码
rest参数
  ES6 引入rest参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。 
 function add(...val) { let sum = 0 sum = val.reduce(((pre, cru) => { return pre + cru })) console.log(sum)}add(1, 2, 3) } add(1,2,3)复制代码
name属性
  函数的name属性,返回该函数的函数名 
 function add(...val) { ···} add.name //add复制代码
箭头函数
let f = v => v //相当于 let f = function (v) { return v }复制代码
如果需要多个参数,则可以把参数放入圆括号中
  let add = (num1, num2) => num1 + num2 
 如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
  var sum = (num1, num2) => { return num1 + num2; } 
   注意点 
 - 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
 - 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
 - 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
 - 不可以使用yield命令,因此箭头函数不能用作Generator函数。
 
尾递归
   函数调用自身,称为递归。如果尾调用自身,就称为尾递归。  
    递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。  
 function factorial(n) { if (n === 1) return 1; return n * factorial(n - 1); } factorial(5) // 120复制代码
   上面代码是一个阶乘函数,计算n的阶乘,最多需要保存n个调用记录,复杂度O(n)。  
     如果改写成尾递归,只保留一个调用记录,复杂度O(1)。  
 function factorial(n, total) { if (n === 1) return total; return factorial(n - 1, n * total); } factorial(5, 1) // 120复制代码
数组的拓展
拓展运算符
含义
   扩展运算符(spread)是三个点(...)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列  
 console.log(...[1,2,3]) //1 2 3
console.log(1,...[2,4,5],6) //1 2 4 5 6复制代码 替代apply方法
下面是一个利用Math.max求最大值的例子
//ES5
Math.max.apply(null, [1, 2, 3]),//3
//ES6   	 
Math.max(...[1, 2, 3])//3复制代码 拓展运算符的运用
- 复制数组
 
let arr1 = [1,2] let arr2 = arr1 arr2[1] = 'a' console.log(arr1,arr2) //[ 1, 'a' ] [ 1, 'a' ]复制代码
  数组是一个复杂类型,直接用等号赋值的话实际上只是复制了它的指针,即arr1、arr2指向的是同一块内存。 
 //ES5 let arr1 = [1,2] let arr2 = arr1.concat() //拓展运算符 let arr1 = [1,2] let arr2 = [...arr1]复制代码
- 合并数组
 
  扩展运算符提供了数组合并的新写法。 
 const arr1 = ['a', 'b']; const arr2 = ['c']; const arr3 = ['d', 'e']; // ES5 的合并数组 arr1.concat(arr2, arr3); // [ 'a', 'b', 'c', 'd', 'e' ] // ES6 的合并数组 [...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]复制代码
  不过,这两种方法都是浅拷贝,使用的时候需要注意。 
 const a1 = [{ foo: 1 }];
const a2 = [{ bar: 2 }];
const a3 = a1.concat(a2);
const a4 = [...a1, ...a2];
a3[0] === a1[0] // true a4[0] === a1[0] // true复制代码 Array.from
   Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。  
    下面是一个类似数组的对象,Array.from将它转为真正的数组。  
 let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; // ES5的写法 var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c'] // ES6的写法 let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']复制代码
Array.of()
  Array.of方法用于将一组值,转换为数组。 
 Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1复制代码 entries(),keys() 和 values()
  ES6提供三个新的方法——entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。 
 for (let index of ['a', 'b'].keys()) { console.log(index); } // 0 // 1 for (let elem of ['a', 'b'].values()) { console.log(elem); } // 'a' // 'b' for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem); } // 0 "a" // 1 "b"复制代码
  
 

京公网安备 11010502036488号