ES6 箭头函数讲解 你正确使用了吗?
箭头函数是es6的一种函数的简写方法。在ES6中允许使用“箭头”(=>)定义函数,之前没有接触过箭头函数的人可能会惊讶于其代码的简洁。
一、先来几个简单的箭头函数
var f = v = > v; //等同于 var f = function(v){ return v; } var sum = (num1,num2) => num1+num2 ; //等同于 var sum = function(num1,num2){ return num1+num2 } [1,2,3].map(function (x) { return x * x; }); // 箭头函数写法 [1,2,3].map(x => x * x);//简洁了许多
从例子我们可以看出,函数省略了function,花括号‘{}’用‘=>’代替了,这种写法更简洁了。
除了简洁之外,箭头函数还有另外一个优点,就是函数体内的this的指向始终是指向定义它所在的对象,而不会指向调用它的对象,我们知道es5中的函数是谁执行它,它就指向谁。
二、箭头函数的用法
1、如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分。
const hello = () => 'hello'; const sum = (num1, num2) => num1 + num2;
2、如果箭头函数的代码块部分多于一条语句,就要使用大括号将它们括起来,并且使用return语句返回。
const sum = (x, y) => { let z= 0; if(x && y){ z= x + y; } return z; }
3、如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
const getInfo = id => ({ id: id, name: "hello" });
三、箭头函数注意事项
A、箭头函数的this指向
对于普通函数来说,内部的this指向函数运行时所在的对象。箭头函数没有自己的this对象,内部的this就是定义时上层作用域中的this。箭头函数this为父作用域的this,不是调用时的this,箭头函数的this永远指向其父作用域,任何方法都改变不了,包括call,apply,bind。
箭头函数内部的this指向是固定的,相比之下,普通函数的this指向是可变的。
将ES6转成ES5,发现其实只是所谓的箭头函数的this只是从外面”借“来的。
// ES6 function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } // ES5 function foo() { var _this = this; setTimeout(function () { console.log('id:', _this.id); }, 100); }
在setInterval中,其实是没有this.s2的,所以它的值不会变化。
function test() { this.s1 = 0; this.s2 = 0; // 箭头函数 setInterval(() => this.s1++, 1000); // 普通函数 setInterval(function () { this.s2++; }, 1000); } s1 // 1 s2 // 0
普通函数修改之后可以修改s2
//普通函数 setInterval(function () { let _this = this; _this.s2++; }, 1000);
在这里也能看到箭头函数的this的指向,可以发现箭头函数非常适合来做回调。
B、箭头函数不能作为构造函数,不能使用new.
//构造函数如下: function Person(p){ this.name = p.name; } //如果用箭头函数作为构造函数,则如下 var Person = (p) => { this.name = p.name; }
由于this必须是对象实例,而箭头函数是没有实例的,不能作为构造函数,这个好理解。因为箭头函数根本没有自己的this,拿甚构造?所以箭头函数也就不能用作构造函数。也不能使用new关键词。
C、箭头函数没有arguments,caller,callee。
像this一样,arguments指向外层函数的对应变量,像类似的兄弟还有super、new.target
function hello() { setTimeout(() => { console.log('args:', arguments); }, 1000); } hello(1,2,3,4) // args: [1, 2, 3, 4]
也因为这个this的问题,箭头函数也不能用call()、apply()、bind()这些方法去改变this的指向,因此箭头函数的this是”静态“的。
D、箭头函数通过call和apply调用,不会改变this指向,只会传入参数
let obj2 = { a: 10, b: function(n) { let f = (n) => n + this.a; return f(n); }, c: function(n) { let f = (n) => n + this.a; let m = { a: 20 }; return f.call(m,n); } }; console.log(obj2.b(1)); // 11 console.log(obj2.c(1)); // 11
E、 箭头函数没有原型属性
var a = ()=>{ return 1; } function b(){ return 2; } console.log(a.prototype); // undefined console.log(b.prototype); // {constructor: ƒ}
F、箭头函数返回对象时,要加一个小括号
var func = () => ({ foo: 1 }); //正确 var func = () => { foo: 1 }; //错误