ES6函数比对ES5函数

2,007 阅读6分钟

简介

这里只做简单的ES6函数与ES5函数对比,把ES6函数中新增的方法或者用法介绍一下。方便大家学习、记忆。随着社会发展,浏览器肯定会在不久全部支持ES6语法,因为现在的IE8用户都很少了,做web前端将不再受此束缚!

函数参数的默认值

其他语言已经支持函数参数默认值,咱们Js也不会落后的。例:

//es6写法
/**
 * @a {number} 默认值10
 * @b {number} 默认值20
 * */
function fn(a=10,b=20){
	console.log(a,b);
}
fn();//没有传递参数
fn(1,3);//传递了参数

//es5写法
/**
 * @a {number} 默认值10
 * @b {number} 默认值20
 * */
function fn(a, b) {
  a = a || 10;//设置默认值
  b = b || 20;//设置默认值
  console.log(a, b);
}	
  1. 先说说es5写法这种写法,如果a传递的是false或者(求值为false的值) 则a会使用默认值10,这样代码就没有按照我们期望的那样去执行。
//修改es5写法让它实现类似于es6:
//es5写法
/**
 * @a {number} 默认值10
 * @b {number} 默认值20
 * */
function fn(a, b) {
   a = a!==undefined?a:10;//设置默认值
   b = b!==undefined?b:20;//设置默认值
  console.log(a, b);
}	
  1. es6写法如果传入undefined,将触发该参数等于默认值,其他值不会触发默认值。
  2. es6设置默认参数值,在函数体内不允许再次使用let或者const声明。例:
/**
 * es6写法
 * @a {number} 默认值10
 * @b {number} 默认值20
 * */
function fn(a=10,b=20){
    let a=100;//会报错哦!
    const b=20;//会报错哦!
	console.log(a,b);
}
  1. 设置参数默认值会产生单独的作用域。
/**
 * es6写法
 * 默认值会产生单独的作用域,作用域的代码也是按照先左后右顺序执行。
 * @a {number} 默认值10
 * @b {number} 默认值10+20
 * */
function fn(a=10,b=a+20){//如果这里是(a=b+20,b=10)调用时a没有传递参数此时会报错!
	console.log(a,b);
}
//复杂的例子
/*-----------一条华丽的分割线-------------*/

/**
 * ----------默认值会产生单独的作用域-----------
 * 调用函数fn 时,未传递参数,【默认参数单独作用域】a值为undefined,b值为undefined。
 * 当执行b()函数时,则查找到a值为undefined,不在查找全局a。
 * 因此为结果为:a的值为: undefined
 * */
var a='全局变量';
function fn(a,b=function(){ console.log('a的值为:',a);}){
	b();
}
fn();//a的值为: undefined

/**
 * ----------默认值会产生单独的作用域-----------
 * 调用函数fn 时,未传递参数,b值为undefined。
 * 当执行b()函数时,则寻找a值发现全局a。
 * 因此为结果为:a的值为: 全局变量
 * */
var a='全局变量';
function fn(b=function(){ console.log('a的值为:',a);}){
	b();
}
fn();//a的值为: 全局变量

**
 * 现在再来理解一下这个。看看你能答对吗?
 * */
var a = '小小坤';
function fn(a, y = function() {a = '小小坤1';}) {
   var a = '小小坤2';
   y();
  console.log(a);
}

fn() // 答案是?
console.log(a); // 答案是?
  1. 使用参数默认值时,函数不能有同名参数。
function fn(a,a,b){
	console.log(a,b);//不报错
}
function fn(a,a,b=1){
	console.log(a,b);//报错
}

rest 参数

ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。例:

//es6写法
/**
 * @b {arry} 参数列表
 *  
 * */
function fn(...b){
	b.push('小小坤');
	console.log(b);
}
fn(1,'20');//[1, "20", "小小坤"]

//es5写法
/**
 * @a {number} 参数a
 * @b {number} 参数b
 * */
function fn(a, b) {
   var arg=[].slice.call(arguments);
   arg.push('小小坤');
   console.log(arg);
}

需要注意的是:

  1. 函数length 属性不包含rest 参数
(function(a) {}).length  // 1
(function(...a) {}).length  // 0
(function(a, ...b) {}).length  // 1
  1. rest 参数不可以这样使用,只能是最后一个参数
function fn (a,...b,d){
   //会报错!	
}

箭头函数

使用时注意事项:

1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
简单例子
/*-----------例子--1------*/
//es6写法
var fn = n => n;

//等同于es5 写法
var fn = function(n) {
  return n;
};
/*-----------例子--2------*/
//es6写法
var fn = () => 5;
// 等同于 es5 写法
var fn = function () { return 5 };
/*-----------例子--3------*/
//es6写法
var sum = (n1, n2) => n1 + n2;
// 等同于es5 写法
var sum = function(n1, n2) {
  return n1 + n2;
};

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

/*-----------例子--4------*/
//es6写法
var sum = (n1, n2) => { return n1+n2; }

//由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
// 报错
let fn = id => { id: id, age: 18 };

// 不报错
let fn = id => ({ id: id, age: 18  });
/*-----------例子--5------*/

function fn() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

var id = 21;

fn.call({ id: 42 });
// id: 42


//ES5代码需要这样写
function fn() {
  var _this=this;//存储this
  setTimeout(function() {
    console.log('id:', _this.id);
  }, 100);
}
var id = 21;
fn.call({ id: 42 });
/**
 *  上面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在fn函数生成时,
 *  而它的真正执行要等到 100 毫秒后。如果是普通函数,执行时this应该指向全局对象window,
 *  这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42}),
 *  所以输出的是42。
 *  箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。
 * 
 *  另外,由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。
 * */
  1. this指向
//this指向lib
var lib={
	option:{
		name:'小小坤'
	},
	init(){
		this.click();
	},
	click(){
		setTimeout(()=>{
			console.log(this.option.name);
		},2000);
	}
}
lib.init();//小小坤
  1. 不能使用构造函数
var des=(n)=>{this.n=n};
new des(1);//des is not a constructor
//因为没有this
  1. 没有arguments属性
var des=(n)=>{console.log(arguments)};
des();//arguments is not defined
//可以这样使用
var des=(...n)=>{console.log(n)};
des(1,2,3,4,5);//[1,2,3,4,5]

总结

经过以上对比可以看出ES6写的代码会越来越少,代码质量也逐渐提升。比如默认参数,箭头函数,还有rest 参数,使用起来爽爆棚!没有在开发环境使用的ES6的同学我们也要抓紧学习啦!