0.为何会出现箭头函数?javascript
1.传统的javascript函数语法并无提供任何的灵活性,每一次你须要定义一个函数时,你都必须输入function () {},这至少会出现两个问题,ES6箭头函数都圆满解决了它,vue
第一个问题:代码输入快了容易输错成 funciton或者functoin或者其它,可是=>这个玩意你要是再写错就只能说有点过度了。java
第二个问题:节省大量代码,咱们先不用管下面的ES6代码为何这样的语法能实现一样的功能,咱们就直观的感觉一下代码量。node
ES5写法:react
function addFive(num){ return num+5; } alert(addFive(10));
ES6写法:面试
var addFive = num=>num+5; alert(addFive(5));
没有function、没有return,没有(),没有{},这些全变成了浮云,世界好清静。express
从上面咱们就能够看到,使用箭头函数不只仅可以避免错误,同时还能让咱们少一丢丢代码,固然实际工做中远比这个代码量节省更多。
一方面是由于积累效应,每一部分少一丢丢合起来就多了,一方面是它还有更能节省代码和大幅提升工做效率的场景。app
接下来咱们就说说今天的主角--箭头函数。函数
ES6标准新增了一种新的函数:Arrow Function(箭头函数),也称“胖箭头函数”, 容许this
使用“箭头”(=>)定义函数,是一种简写的函数表达式。
一、箭头函数语法
在ES5中咱们实现一个求和的函数:
var sum = function(x, y) { return x + y }
要使用箭头函数,能够分两步实现一样的函数功能:
首先使用=>来替代关键词function
var sum = (x, y) => { return x + y }
这个特性很是好!!!
前面咱们已经说过用=>来替代关键词function就意味着不会写错function了,这真是一个绝妙的设计思想!
其次,函数体只有一条返回语句时, 咱们能够省略括号{}和return关键词:
var sum = (x, y) => x + y
再夸张一点点,若是只有一个参数时,()可省略。
这是箭头函数最简洁的形式,经常使用于做用简单的处理函数,好比过滤:
// ES5 var array = ['1', '2345', '567', '89']; array = array.filter(function (item) { return item.length > 2; }); // ["2345", "567"] // ES6 let array = ['1', '2345', '567', '89']; array = array.filter(item => item.length > 2); // ["2345", "567"]
箭头函数的主要使用模式以下:
// 一个参数对应一个表达式 param => expression;// 例如 x => x+2; // 多个参数对应一个表达式 (param [, param]) => expression; //例如 (x,y) => (x + y); // 一个参数对应多个表示式 param => {statements;} //例如 x = > { x++; return x;}; // 多个参数对应多个表达式 ([param] [, param]) => {statements} // 例如 (x,y) => { x++;y++;return x*y;}; //表达式里没有参数 () => expression; //例如var flag = (() => 2)(); flag等于2 () => {statements;} //例如 var flag = (() => {return 1;})(); flag就等于1 //传入一个表达式,返回一个对象 ([param]) => ({ key: value }); //例如 var fuc = (x) => ({key:x}) var object = fuc(1); alert(object);//{key:1}
你们不要以为好多啊,好麻烦,其实这些根本不复杂。投入一次,受益终生。(怎么感受我像卖保险的……),写一两次你就习惯新的写法了。
二、箭头函数中的 this
箭头函数内的this值继承自外围做用域。运行时它会首先到它的父做用域找,若是父做用域仍是箭头函数,那么接着向上找,直到找到咱们要的this指向。
咱们先看一道经典的关于this的面试题:
var name = 'leo'; var teacher = { name: "大彬哥", showName: function () { function showTest() { alert(this.name); } showTest(); } }; teacher.showName();//结果是 leo,而咱们期待的是大彬哥,这里this指向了window,咱们期待指向teacher
你们知道,ES5中的this说好听了叫"灵活",说很差听就是瞎搞,特别容易出问题.并且面试还很是爱考,工做更不用说了,常常给咱们开发捣乱,出现很差调试的bug,用E箭头函数解决这个问题就很驾轻就熟了。
var name = 'leo'; var teacher = { name: "大彬哥", showName: function () { let showTest = ()=>alert(this.name); showTest(); } }; teacher.showName();
箭头函数中的this实际上是父级做用域中的this。箭头函数引用了父级的变量词法做用域就是一个变量的做用在定义的时候就已经被定义好,当在本做用域中找不到变量,就会一直向父做用域中查找,直到找到为止。
因为this在箭头函数中已经按照词法做用域绑定了,因此,用call或者apply调用箭头函数时,没法对this进行绑定,即传入的第一个参数被忽略:
var obj = { birth: 1996, getAge: function (year) { var b = this.birth; // 1996 var fn = (y) => y - this.birth; // this.birth还是1996 return fn.call({birth:1990}, year); } }; obj.getAge(2018); // 22 ( 2018 - 1996)
因为this已经在词法层面完成了绑定,经过call或apply方法调用一个函数时,只是传入了参数而已,对this并无什么影响 。所以,这个设计节省了开发者思考上下文绑定的时间。
三、箭头函数的特性
3.1 箭头函数没有 arguments
箭头函数不只没有this,经常使用的arguments也没有。若是你能获取到arguments,那它
必定是来自父做用域的。
function foo() { return () => console.log(arguments) } foo(1, 2)(3, 4) // 1,2
上例中若是箭头函数有arguments,就应该输出的是3,4而不是1,2。
箭头函数不绑定arguments,取而代之用rest参数…解决
var foo = (...args) => { return args } console.log(foo(1,3,56,36,634,6)) // [1, 3, 56, 36, 634, 6]
箭头函数要实现相似纯函数的效果,必须剔除外部状态。咱们能够看出,箭头函数除了传入的参数以外,真的在普通函数里常见的this、arguments、caller是通通没有的!
若是你在箭头函数引用了this、arguments或者参数以外的变量,那它们必定不是箭头函数自己包含的,而是从父级做用域继承的。
3.2 箭头函数中不能使用 new
let Person = (name) => { this.name = name; }; let one = new Person("galler");
运行该程序,则出现TypeError: Person is not a constructor
3.3 箭头函数能够与变量解构结合使用。
const full = ({ first, last }) => first + ' ' + last; // 等同于 function full(person) { return person.first + ' ' + person.last; } full({first: 1, last: 5}) // '1 5'
3.4 箭头函数没有原型属性
var foo = () => {}; console.log(foo.prototype) //undefined
由此能够看出箭头函数没有原型。
另外一个错误是在原型上使用箭头函数,如:
function A() { this.foo = 1 } A.prototype.bar = () => console.log(this.foo) let a = new A() a.bar() //undefined
一样,箭头函数中的this不是指向A,而是根据变量查找规则回溯到了全局做用域。一样,使用普通函数就不存在问题。箭头函数中不可加new,也就是说箭头函数不能当构造函数进行使用。
3.5 箭头函数不能换行
var func = () => 1; // SyntaxError: expected expression, got '=>'
若是开发中确实一行搞不定,逻辑不少,就加{},你就想怎么换行怎么换行了。
var func = ()=>{ return '来啊!互相伤害啊!'; // 1.加{} 2.加return }
四、箭头函数使用场景
JavaScript中this的故事已是很是古老了,每个函数都有本身的上下文。
如下例子的目的是使用jQuery来展现一个每秒都会更新的时钟:
$('.time').each(function () { setInterval(function () { $(this).text(Date.now()); }, 1000); });
当尝试在setInterval的回调中使用this来引用DOM元素时,很不幸,咱们获得的只是一个属于回调函数自身
上下文的this。一个一般的解决办法是定义一个that或者self变量:
$('.time').each(function () { var self = this; setInterval(function () { $(self).text(Date.now()); }, 1000); });
但当使用箭头函数时,这个问题就不复存在了。由于它不产生属于它本身上下文的this:
$('.time').each(function () { setInterval(() => $(this).text(Date.now()), 1000); });
箭头函数的另外一个用处是简化回调函数。
// 正常函数写法 [1,2,3].map(function (x) { return x * x; }); // 箭头函数写法 [1,2,3].map(x => x * x);
固然也能够在事件监听函数里使用:
document.body.addEventListener('click', event=>console.log(event, this)); // EventObject, BodyElement
五、总结
5.1 箭头函数优势
箭头函数是使用=>语法的函数简写形式。这在语法上与 C#、Java 8 、Python( lambda 函数)和 CoffeeScript 的
相关特性很是类似。
很是简洁的语法,使用箭头函数比普通函数少些动词,如:function或return。
() => { ... } // 零个参数用 () 表示。 x => { ... } // 一个参数能够省略 ()。 (x, y) => { ... } // 多参数不能省略 ()。 若是只有一个return,{}能够省略。
更直观的做用域和 this的绑定,它能让咱们能很好的处理this的指向问题。箭头函数加上let关键字的使用,将会让咱们javascript代码上一个层次。
5.2 箭头函数使用场景
箭头函数适合于无复杂逻辑或者无反作用的纯函数场景下,例如用在map、reduce、filter的回调函数定义
中,另外目前vue、react、node等库,都大量使用箭头函数,直接定义function的状况已经不多了。
各位同窗在写新项目的时候,要不断的琢磨箭头函数使用场景、特色,享受使用箭头函数带来的便利,这样才能更快地成长。