箭头函数
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
箭头函数相当于匿名函数,并且简化了函数定义,将原函数的“function”关键字和函数名都删掉,并使用“=>”连接参数列表和函数体。
举例1:
定义和调用函数(传统写法):
function fn1(a,b){
return a + b;
}
console.log(fn1(1,2)); //输出结果,3
定义和调用函数(ES6中的写法):
var fn2 = (a,b) => a + b;
console.log(fn2(1,2)); //输出结果,3
上方代码中,二者的输出的结果是一样的,但是箭头函数简化了代码量。
举例2:
var fn2 = (a,b) => {
console.log('hello');
return a + b;
};
console.log(fn2(1,2)); //输出结果,3
上方代码分析:
- 如果有且仅有1个参数,则
()
可以省略。 - 在箭头函数中,如果方法体内超过一句话,那就需要在方法体外边加上
{}
括号。 - 如果方法体内有且仅有1条语句,则
{}
可以省略,但前提是,这条语句必须是return
。
This的指向
ES5中,this指向的是函数被调用的对象,而ES6的箭头函数中,this指向的是函数被定义时。
简单来说,箭头函数中的this,是不会变的,是永远绑定在当前的环境下。
举例1
var html = document.querySelector('html');
html.onclick = function(){
setTimeout(function(){
console.log(this);
},1000)
}
打印结果:
改为使用箭头函数:
var html = document.querySelector('html');
html.onclick = function(){
setTimeout(() => {
console.log(this);
},1000)
}
打印结果:
上方代码分析:
- 箭头函数改变了this的指向,使this总是指向词法作用域,也就是外层调用者html。
bind()
除了箭头函数外,ES5中还新增了bind()来改变this的指向。
Function.prototype.bind()
作用:将函数内的this
绑定为obj
,并将函数返回。
call()
、apply()
和bind()
的区别:
- 都能改变this的指向。
call()
和apply()
是立即调用函数。bind()
绑定完this
后,不会立即调用当前函数,而是将函数返回,因此后面还需要再加()
才能调用。bind()
传参的方式和call()
一样。
分析:
- 为什么ES5中要加入
bind()
方法来改版this
的指向呢? - 因为
bind()
不会立即调用当前函数。 bind()
通常使用在回调函数中,因为回调函数并不会立即调用,如果希望在回调函数中改变this
的指向,不妨使用bind()
。
参数默认值
举例1:
传统写法:
function fn(param){
let p = param || 'hello';
console.log(p);
}
ES6写法:
function fn(param = 'hello'){
console.log(param);
}
在ES6中定义方法时,我们可以给方法里的参数加一个默认值(缺省值):
- 方法被调用时,如果没有给参数赋值,那就使用默认值。
- 方法被调用时,如果给参数赋值了新的值,那就使用新的值。
- 默认值的后面,不能再有没有默认值的变量,比如 (a,b,c) 这三个参数,如果给b设置了默认值,那么就一定要给c也设置默认值。
举例2:
let x = 'smyh';
function fn(x=4,y=x){
console.log(x,y);
}
fn('vae');
//此时打印结果为:vae vae 。
如果把第一个参数x改成别的:
let x = 'smyh';
function fn(z,y=x){
console.log(z,y);
}
fn('vae');
//此时打印结果为:vae smyh 。
上方代码分析:
- 参数的默认值可以为同一行里的参数。
- 这种情况下,获取的值也适用默认值的语法。
扩展运算符
扩展运算符可以应用于数组和对象,可以通过在前面加上…把数组或对象转为用逗号分隔的参数序列。
举例1:
let arr = [1,2,3,4,5];
function getarr(a,b,c,d,e){
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);
}
getarr(arr[0],arr[1],arr[2],arr[3],arr[4]);
// 输出结果 1,2,3,4,5
使用扩展运算符:
let arr = [1,2,3,4,5];
function getarr(a,b,c,d,e){
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);
}
getarr(...arr);
// 输出结果 1,2,3,4,5
将扩展运算符用于函数调用,减少了代码量。
举例2:
let arr1 = ['name','type','like'];
let arr2 = arr1;
console.log('arr1:' + arr1);
console.log('arr2:' + arr2);
arr2.push('add');
console.log('arr1:' + arr1);
console.log('arr2:' + arr2);
// 输出结果
// arr1:name,type,like
// arr2:name,type,like
// arr1:name,type,like,add
// arr2:name,type,like,add
上方代码分析:
- arr2里添加了
add
,却发现,arr1里也有这个内容。 - 原因是:
let arr2 = arr1
其实是让arr2指向arr1的地址,也就是说,二者指向的是同一个内存地址。
如果不想让 arr1和arr2指向同一个内存地址,可以借助扩展运算符来实现。
let arr1 = ['name','type','like'];
let arr2 = [...arr1];
console.log('arr1:' + arr1);
console.log('arr2:' + arr2);
arr2.push('add');
console.log('arr1:' + arr1);
console.log('arr2:' + arr2);
// 输出结果
// arr1:name,type,like
// arr2:name,type,like
// arr1:name,type,like
// arr2:name,type,like,add
明白了这个例子,就可以避免开发中很多逻辑上的bug。
Rest 运算符
rest运算符也是三个点号,不过其功能与扩展运算符恰好相反,把逗号隔开的值序列组合成一个数组。
function fn(first,second,...arg){
console.log(arg.length);
}
fn(0,1,2,3,4,5,6);
//输出结果 5
- 调用 fn() 时,里面有七个参数,而 arg 指的是剩余部分(除去了 first 和 second) 。
- 通常情况下,扩展运算符在函数的调用中使用,rest 运算符在函数的声明中使用。