箭头函数表达式的语法比函数表达式更简洁,并且没有自己的 this,arguments,super 或 new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
引入箭头函数有两个方面的作用:
- 更简短的函数
- 不绑定 this
更短的函数
1 2 3
| const add = (a, b) => a + b; const square = x => x * x; const createObj = () => ({ key: 1 });
|
没有单独的 this
在箭头函数出现之前,每一个函数根据它是如何被调用的来定义这个函数的 this 值
- 如果这个函数是构造函数,this 指针指向新构造的对象
- 在严格模式下,this 指向 undefined
- 如果该函数是一个对象的方法,那么它的 this 指针指向这个对象
- 其他的函数中的 this 指向全局对象
1 2 3 4 5 6 7 8 9 10 11 12
| function Person() { this.age = 0;
setInterval(function growUp() { this.age++; }, 1000); }
var p = new Person();
|
在 ECMAScript3/5 中,通过将 this 值分配给封闭的变量,可以解决 this 问题
1 2 3 4 5 6 7 8 9
| function Person() { var that = this; that.age = 0;
setInterval(function growUp() { that.age++; }, 1000); }
|
或者可以创建绑定函数,以便将预先分配的 this 值传递到绑定的目标函数
箭头函数不会创建自己的 this,它只会从自己的作用域链的上一层继承 this。因此,在下面的代码中,传递给 setInterval 的函数内的 this 与 Person 函数中的 this 值相同。
1 2 3 4 5 6 7 8 9
| function Person(){ this.age = 0;
setInterval(() => { this.age++; }, 1000); }
var p = new Person();
|
通过 call,apply,bind 调用
由于箭头函数没有自己的 this 指针,通过 call()或 apply()方法调用一个函数时,只能传递参数,不能绑定 this,他们的第一个参数会被忽略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| var adder = { base : 1,
add : function(a) { var f = v => v + this.base; return f(a); },
addThruCall: function(a) { var f = v => v + this.base; var b = { base : 2 };
return f.call(b, a); } };
console.log(adder.add(1)); console.log(adder.addThruCall(1));
|
不绑定 arguments
箭头函数不绑定 arguments 对象,因此 arguments 只是引用了封闭作用域内的 arguments。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var arguments = [1, 2, 3]; var arr = () => arguments[0];
arr();
function foo(n) { var f = () => arguments[0] + n; return f(); }
foo(1); foo(2); foo(3); foo(3,2);
|
使用剩余参数来达到原有的意图:
1 2 3 4 5 6 7 8 9 10 11
| function foo(arg) { var f = (...args) => args[0]; return f(arg); } foo(1);
function foo(arg1,arg2) { var f = (...args) => args[1]; return f(arg1,arg2); } foo(1,2);
|
箭头函数不适合作为方法
1 2 3 4 5 6 7 8 9 10 11 12
| 'use strict'; var obj = { i: 10, b: () => console.log(this.i, this), c: function() { console.log( this.i, this) } } obj.b();
obj.c();
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 'use strict'; var obj = { a: 10 };
Object.defineProperty(obj, "b", { get: () => { console.log(this.a, typeof this.a, this); return this.a+10; } });
obj.b;
|
箭头函数不能用作构造函数
箭头函数不能用作构造器,和 new一起用会抛出错误。
1 2
| var Foo = () => {}; var foo = new Foo();
|
箭头函数没有 prototype 属性
1 2
| var Foo = () => {}; console.log(Foo.prototype);
|
箭头函数内不能使用 yield
yield 关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作函数生成器。
什么是 yield?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield
换行
箭头函数在参数和箭头之间不能换行。
但是,可以通过在 ‘=>’ 之后换行,或者用 ‘( )’、'{ }'来实现换行,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var func = (a, b, c) => 1;
var func = (a, b, c) => ( 1 );
var func = (a, b, c) => { return 1 };
var func = ( a, b, c ) => 1;
|
解析顺序
虽然箭头函数中的箭头不是运算符,但箭头函数具有与常规函数不同的特殊运算符优先级解析规则。
1 2 3 4 5 6 7 8
| let callback;
callback = callback || function() {};
callback = callback || () => {};
callback = callback || (() => {});
|