ES6-函数的扩展

1. 函数参数默认值

 

在ES5中我们想给函数的参数设置默认值通常是通过短路表达式来操作:

function log(x, y) {
  y = y || 'World';
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello World

ES6则允许为函数的参数设置默认值,即直接写在参数定义的后面。

function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

2. rest参数

形式为“...变量名”,用于获取函数的多余参数。rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中。注意,rest参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

function add(...values) {
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2, 5, 3) // 10

3. 扩展运算符(spread

是三个点(…)。它好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列,该运算符主要用于函数调用。

function add(x, y) {
  return x + y;
}

var numbers = [4, 38];
add(...numbers) // 42

这里在举个例子,我们先从Math.max()函数说起,Math.max后面可以接任意个参数,最后返回所有参数中的最大值。比如 

alert(Math.max(5,8))   //8
alert(Math.max(5,7,9,3,1,6))   //9

但是在很多情况下,我们需要找出数组中最大的元素。

var arr=[5,7,9,1]
alert(Math.max(arr))    // 这样却是不行的。一定要这样写

function getMax(arr){
    var arrLen=arr.length;
    for(var i=0,ret=arr[0];i<arrLen;i++){
        ret=Math.max(ret,arr[i]);       
    }
    return ret;
}

这样写麻烦而且低效。如果用 apply呢,看代码:

function getMax2(arr){
    return Math.max.apply(null,arr);
}

那如果使用ES6呢

function getMax3(arr){
    return Math.max(...arr);
}
getMax3(arr) //9

4. 箭头函数

在箭头函数出现之前,每个新定义的函数都有它自己的 this值(在构造函数的情况下是一个新对象,在严格模式的函数调用中为 undefined,如果该函数被作为“对象方法”调用则为基础对象等),寻找This的指向更是令人厌烦。所以在ES6引入了箭头函数,其优势更简短的函数并且不绑定this。箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。至于什么说是箭头函数呢?因为他是由箭头定义的啊,O(∩_∩)O。

(1) 如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分 

(2) 如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。

箭头函数的基本语法:


(参数1, 参数2, …, 参数N) => { 函数声明 } //相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; } (参数1, 参数2, …, 参数N) => 表达式(单一) // 当只有一个参数时,圆括号是可选的: (单一参数) => {函数声明} 单一参数 => {函数声明}
v => v;

 //上面的箭头函数等同于:

function(v) {
  return v;
};
// 没有参数的函数应该写成一对圆括号。 () => {函数声明}

高级语法

//加括号的函数体返回对象字面表达式:
参数=> ({foo: bar})

//支持剩余参数和默认参数
(参数1, 参数2, ...rest) => {函数声明}
(参数1 = 默认值1,参数2, …, 参数N = 默认值N) => {函数声明}

//同样支持参数列表解构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6

箭头函数可以有一个“简写体”或常见的“块体”。

在一个简写体中,只需要一个表达式,并附加一个隐式的返回值。在块体中,必须使用明确的return语句。

var func = x => x * x;                  
// 简写函数 省略return

var func = (x, y) => { return x + y; }; 
//常规编写 明确的返回值

返回对象字面量

记住用params => {object:literal}这种简单的语法返回对象字面量是行不通的。

var func = () => { foo: 1 };               
// Calling func() returns undefined!

var func = () => { foo: function() {} };   
// SyntaxError: function statement requires a name

这是因为花括号({} )里面的代码被解析为一系列语句(即 foo 被认为是一个标签,而非对象字面量的组成部分)。

所以,记得用圆括号把对象字面量包起来:

var func = () => ({foo: 1});

箭头函数内定义的变量及其作用域

this指向问题

注意:

1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。通过 call 或 apply 调用由于 箭头函数没有自己的this指针,通过 call() 或 apply() 方法改变this指向。

上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到100毫秒后。如果是普通函数,执行时this应该指向全局对象window,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42}),所以输出的是42。即箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。

2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

 

posted @ 2019-01-04 17:41  Smile_ruo  阅读(167)  评论(0编辑  收藏  举报