箭头函数与普通函数的区别(ES6)
目录
- 相比普通函数更简洁的语法
- 没有this
- 使用call()和apply()调用
- 捕获其所在上下文的 this 值,作为自己的 this 值
- 不能使用new
- 不绑定arguments,用rest参数...解决
- 箭头函数没有原型属性
- 不能简单返回对象字面量
- 箭头函数不能当做Generator函数,不能使用yield关键字
- 箭头函数不能换行
正文
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
为什么叫Arrow Function?因为它的定义用的就是一个箭头:
语法:
//1、没有形参的时候
let fun = () => console.log('我是箭头函数');
fun();
//2、只有一个形参的时候()可以省略
let fun2 = a => console.log(a);
fun2('aaa');
//3、俩个及俩个以上的形参的时候
let fun3 = (x,y) =>console.log(x,y); //函数体只包含一个表达式则省略return 默认返回,也可省略`{ }`
fun3(24,44);
//4、俩个形参以及函数体多条语句表达式,这时候就不能省略{ ... }和return。
let fun4 = (x,y) => {
console.log(x,y);
return x+y; //必须加return才有返回值
}
//5、如果要返回对象时需要用小括号包起来,因为大括号被占用解释为代码块了,正确写法
let fun5 = ()=>({ foo: x }) //如果x => { foo: x } //则语法出错
箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式,一种只包含一个表达式,连{ ... }和return都省略掉了。还有一种可以包含多条语句,这时候就不能省略{ ... }和return。
相比普通函数更简洁的语法
箭头函数:
var a = ()=>{
return 1;
}
普通函数:
function a(){
return 1;
}
和普通函数对比
// 有1个参数
let f = v => v;
// 等同于
let f = function (v){return v};
// 有多个参数
let f = (v, i) => {return v + i};
// 等同于
let f = function (v, i){return v + i};
// 没参数
let f = () => 1;
// 等同于
let f = function (){return 1};
// 正常函数写法
function f (p) {
return p.a + ':' + p.b;
}
// 箭头函数写法
let f = ({a, b}) => a + ':' + b;
简化回调函数:
// 正常函数写法
[1, 2, 3].map(function (x){
return x * x;
})
// 箭头函数写法
[1, 2, 3].map(x => x * x);
没有this,所以更不能改变this指向
在箭头函数出现之前,每个新定义的函数都有其自己的 this 值
var myObject = {
value:1,
getValue:function(){
console.log(this.value)
},
double:function(){
return function(){ //this指向double函数内不存在的value
console.log(this.value = this.value * 2);
}
}
}
/*希望value乘以2*/
myObject.double()(); //NaN
myObject.getValue(); //1
使用箭头函数
var myObject = {
value:1,
getValue:function(){
console.log(this.value)
},
double:function(){
return ()=>{
console.log(this.value = this.value * 2);
}
}
}
/*希望value乘以2*/
myObject.double()(); //2
myObject.getValue(); //2
call、apply、bind 并不会影响 this 的指向
由于 this 已经在词法层面完成了绑定,通过 call() 或 apply() 方法调用一个函数时,只是传入了参数而已,对 this 并没有什么影响:
var obj = {
value:1,
add:function(a){
var f = (v) => v + this.value; //a==v,3+1
return f(a);
},
addThruCall:function(a){
var f = (v) => v + this.value; //此this指向obj.value
var b = {value:2};
return f.call(b,a); //f函数并非指向b,只是传入了a参数而已
}
}
console.log(obj.add(3)); //4
console.log(obj.addThruCall(4)); //5
箭头函数不绑定this,会捕获其所在上下文的 this 值,作为自己的 this 值
(箭头函数不会重新绑定this,普通函数会)
var obj = {
a: 10,
b: () => {
console.log(this.a); // undefined
console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
},
c: function() {
console.log(this.a); // 10
console.log(this); // {a: 10, b: ƒ, c: ƒ}
}
}
obj.b();
obj.c();
var obj = {
a: 10,
b: function(){
console.log(this.a); //10
},
c: function() {
return ()=>{
console.log(this.a); //10
}
}
}
obj.b();
obj.c()();
不能使用new
箭头函数是匿名函数,不能作为构造函数,不能使用new
var B = ()=>{
value:1;
}
var b = new B(); //TypeError: B is not a constructor
不绑定arguments,用rest参数...解决
/*常规函数使用arguments*/
function test1(a){
console.log(arguments); //1
}
/*箭头函数不能使用arguments*/
var test2 = (a)=>{console.log(arguments)} //ReferenceError: arguments is not defined
/*箭头函数使用reset参数...解决*/
let test3=(...a)=>{console.log(a[1])} //22
test1(1);
test2(2);
test3(33,22,44);
箭头函数没有原型属性
var a = ()=>{
return 1;
}
function b(){
return 2;
}
console.log(a.prototype);//undefined
console.log(b.prototype);//object{...}
不能简单返回对象字面量
如果要返回对象时需要用小括号包起来,因为大括号被占用解释为代码块了,正确写法
let fun5 = ()=>({ foo: x }) //如果x => { foo: x } //则语法出错
箭头函数不能当做Generator函数,不能使用yield关键字
箭头函数不能换行
let a = ()
=>1; //SyntaxError: Unexpected token =>
总结
箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向,如 call()
, bind()
, apply()
普通函数的this指向调用它的那个对象