前言
对于ES6新增的箭头函数,相关的介绍可以查看MDN - Arrow_functions以及ECMAScript 6 入门。
引入
首先我们先看下面一段代码:
这里为什么使用箭头函数定义的方法,不能访问到对象内的属性呢?
Function定义的方法
这里我们先说为什么使用function定义的方法能够按照我们的预计正确读取到i的值。
首先,我们要明白,使用function定义的方法MDN - Functions:
在函数执行时,this 关键字并不会指向正在运行的函数本身,而是指向调用该函数的对象。
那么,也就是说,我们使用function定义的函数,在定义时,它并不知道这个this会指向哪里,只有在运行的时候才能明确this的值。
在这里,我们是使用obj.func,调用函数func的对象是obj,所以函数func的this被指向调用它的对象obj。所以此时func内的this是能够通过this.i访问到obj.i的。
那么如果我们像下面这样调用:
此时调用函数func的是window对象,所以函数func的this被指向了window,而window不具有i属性,显示undefined。
箭头函数定义的方法
接下来再来说说为什么使用箭头函数定义的方法不能访问到obj里的值。
首先,我们还是要明白MDN - Arrow_functions:
箭头函数拥有词法作用域的this值(即不会新产生自己作用域下的this, arguments, super 和 new.target 等对象)
箭头函数本身不具有this,它会直接绑定到它的词法作用域内的this,也就是定义它时的作用域内的this值。所以试图使用apply,call等方法修改箭头函数的this是不会成功的,因为箭头函数自身没有this。所以我们来看下面一段代码:
可以看出,箭头函数是直接使用的作用域内的this,apply等方法是无效的。为了加深理解,我们再来看下面一段代码:
通过这段代码,我们应该可以明确的看出来,箭头函数是直接使用的它词法作用域内的this,也就是定义它时的作用域内的this。当我们修改它的作用域内的this值,也就是func的this值时,在箭头函数内也可以反映出来。用作对比,我们看下使用function定义的函数:
想一下,这段函数的输出应该是什么,回顾下我们前面提到的:
在函数执行时,this 关键字并不会指向正在运行的函数本身,而是指向调用该函数的对象。
那么在这里,不管函数func内的this究竟是指向哪里,但是调用func返回的匿名函数的对象是window。这里需要明白,函数也是值,func只是返回了一个值,最终调用这个值的对象实际是window。所以,这里的控制台的打印结果应该是:
即匿名函数的this值是指向的window。跟上面的箭头函数的结果做对比,是不是对箭头函数拥有词法作用域的this值,理解更深了呢?
小结
此时再来看看我们的引入里面的问题,为什么Object内使用箭头函数定义的方法,在使用Object调用时,箭头函数内的this无法访问到Object对象?原因还是我们那句话:使用词法作用域内的this。Object对象是不会新建自己的this值的,所以箭头函数会一直使用词法作用域内的this,也就是window。
后记
箭头函数的出现使的在 JavaScript 中的this值更加符合我们的预期,避免了一些意料之外的问题出现。但是某些时候,例如说在Object里定义的函数,使用方法调用时不会使用调用它的对象作为this值。所以,我们应该理解箭头函数和普通定义的函数的区别,正确的使用他们。