简介
这里只做简单的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);
}
- 先说说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);
}
- es6写法如果传入undefined,将触发该参数等于默认值,其他值不会触发默认值。
- 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);
}
- 设置参数默认值会产生单独的作用域。
/**
* 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); // 答案是?
- 使用参数默认值时,函数不能有同名参数。
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);
}
需要注意的是:
- 函数length 属性不包含rest 参数
(function(a) {}).length // 1
(function(...a) {}).length // 0
(function(a, ...b) {}).length // 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的指向。
* */
- this指向
//this指向lib
var lib={
option:{
name:'小小坤'
},
init(){
this.click();
},
click(){
setTimeout(()=>{
console.log(this.option.name);
},2000);
}
}
lib.init();//小小坤
- 不能使用构造函数
var des=(n)=>{this.n=n};
new des(1);//des is not a constructor
//因为没有this
- 没有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的同学我们也要抓紧学习啦!